Docker 构建无法访问 ADO 工件

Docker build unable to access ADO artifacts

使用 Docker 在本地使用我项目的 .dockerfile 执行构建,我无法访问我们的私有 ADO 工件,并显示 401 未授权。

我已经在所有可访问的组织中为我的 ADO 帐户生成了一个带有“打包(读取)”的 PAT,它还没有过期。

这在 ADO 构建管道中使用“npmAuthenticate”任务并将其指向项目的 .npmrc,但在本地,Docker 无法进行身份验证。


.dockerfile

FROM node:12 AS clientBuilder
ARG NPM_TOKEN
ADD . /client
WORKDIR /client

RUN wget -qO- https://aka.ms/install-artifacts-credprovider.sh | bash
ENV NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED true
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS '{"endpointCredentials": [{"endpoint":"https://<ADO FEED>/nuget/v3/index.json", "username":"docker", "password":"'${NPM_TOKEN}'"}]}'

# the following line fails to authenticate
RUN npm ci

.npmrc(项目)

registry=<PROVIDED BY ADO ARTIFACTS>
always-auth=true

Bash 命令

docker build . --build-arg NPM_TOKEN=<PAT>

以上结果如下:

Step 9/18 : RUN echo ${VSS_NUGET_EXTERNAL_FEED_ENDPOINTS}
 ---> Running in 6407b058be7d
{"endpointCredentials": [{"endpoint":"https://*****/nuget/v3/index.json", "username":"docker", "password":"*****"}]}
Step 11/18 : RUN npm ci
 ---> Running in 33a180c7b4c1
npm ERR! code E401
npm ERR! Unable to authenticate, need: Bearer authorization_uri=https://****, Basic realm="https://pkgsprodeus21.pkgs.visualstudio.com/", TFS-Federated

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2020-12-07T19_21_50_935Z-debug.log
The command '/bin/sh -c npm ci' returned a non-zero code: 1

我注意到,如果我使用与我的用户 .npmrc 中提供的相同凭据配置项目的 .npmrc,它工作正常。显然我不希望项目的 .npmrc 有任何身份验证信息。

如果您需要比我上面提供的更多的信息,请告诉我。

这是我过去用于对私有 Azure DevOps NuGet 和 NPM 源进行身份验证的基本“devtools”映像。 PAT 需要对 NPM 进行 Base64 编码,但不需要对 NuGet 进行编码。这有点奇怪。我不能保证没有更好的方法来做到这一点。

ARG SDKVersion=3.1
FROM mcr.microsoft.com/dotnet/core/sdk:${SDKVersion} AS build-env
# Contains NPM/NodeJS for webpack and all appropriate PATs/configuration for pulling NPM and NuGet packages from private feeds
ARG NugetPAT
ARG B64PAT
ARG SDKVersion=3.1

ENV Configuration Release

ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS \
    "{\"endpointCredentials\": [{\"endpoint\":\"https://pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/nuget/v3/index.json\", \"username\":\"docker\", \"password\":\"${NugetPAT}\"}]}"
RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh  | bash
RUN apt-get update -yq \
    && apt-get install curl gnupg -yq \
    && curl -sL https://deb.nodesource.com/setup_12.x | bash \
    && apt-get install nodejs -yq
    
WORKDIR /app
RUN echo '<?xml version="1.0" encoding="UTF-8"?><configuration><packageSources><add key="public" value="https://api.nuget.org/v3/index.json" /><add key="projectname-common" value="https://pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/nuget/v3/index.json" /></packageSources></configuration>' > NuGet.config
RUN echo \; begin auth token > /root/.npmrc && \
echo //pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/registry/:username=orgname >> /root/.npmrc && \ 
echo //pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/registry/:_password=${B64PAT} >> /root/.npmrc && \
echo //pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/registry/:email=npm requires email to be set but doesn''t use the value >> /root/.npmrc && \
echo //pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/:username=orgname >> /root/.npmrc && \
echo //pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/:_password=${B64PAT} >> /root/.npmrc && \
echo //pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/:email=npm requires email to be set but doesn''t use the value >> /root/.npmrc && \
echo \; end auth token >> /root/.npmrc 

如果您在 Windows 上进行开发,您可以使用 vsts-npm-auth 获取凭据并将其注入您的用户级别 .npmrc 定期归档。

如果您在 Linux 或 Mac 上开发,则不支持 vsts-npm-auth。您需要使用 Packaging read & write 范围生成个人访问令牌 (PAT),并使用 Base64 对该 PAT 进行编码。然后使用Base64编码值到你的用户级.npmrc文件中。

查看更多详情,您可以查看以下文章:

我使用了@daniel-mann方法。我刚离开 PAT。

我不使用 PAT 的原因:

  • 过期
  • 与用户相关,我不想让它与我的帐户相关,也不想创建 build 用户。

处理方法:

  1. 在根文件夹中创建一个 .npmrc 没有密码的文件

.npmrc

//pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/registry/:username=orgname 
//pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/registry/:email=npm requires email to be set but does not use the value
//pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/:username=orgname 
//pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/npm/:email=npm requires email to be set but does not use the value
  1. 添加 npmAuthenticate@0 任务以将凭据注入 .npmrc 文件
 task: npmAuthenticate@0
  inputs:
    workingFile: .npmrc
  1. 对于 dockerfile,我保留了相同的结构,只是替换了 .npmrc 部分

Dockerfile

ARG SDKVersion=3.1
FROM mcr.microsoft.com/dotnet/core/sdk:${SDKVersion} AS build-env
# Contains NPM/NodeJS for webpack and all appropriate PATs/configuration for pulling NPM and NuGet packages from private feeds
ARG NugetPAT
ARG SDKVersion=3.1

ENV Configuration Release

ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS \
    "{\"endpointCredentials\": [{\"endpoint\":\"https://pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/nuget/v3/index.json\", \"username\":\"docker\", \"password\":\"${NugetPAT}\"}]}"
RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh  | bash
RUN apt-get update -yq \
    && apt-get install curl gnupg -yq \
    && curl -sL https://deb.nodesource.com/setup_12.x | bash \
    && apt-get install nodejs -yq
    
WORKDIR /app
RUN echo '<?xml version="1.0" encoding="UTF-8"?><configuration><packageSources><add key="public" value="https://api.nuget.org/v3/index.json" /><add key="projectname-common" value="https://pkgs.dev.azure.com/orgname/projectname/_packaging/projectname-common/nuget/v3/index.json" /></packageSources></configuration>' > NuGet.config

# copying the npmrc file with credentials
# don't need to authenticate as it is authenticated by 
# the npmAuthenticate task
COPY .npmrc /root/.npmrc
  1. 将 Nuget PAT 替换为 Azure System.AccessToken
docker build . --build-arg NPM_TOKEN=$(System.AccessToken)

Azure 管道类似于:


- task: npmAuthenticate@0
  displayName: Authenticate .npmrc file
  inputs:
    workingFile: .npmrc

- task: PowerShell@2
  displayName: build container
  inputs:
    targetType: "inline"
    script: |
      docker build . --build-arg NPM_TOKEN=$(System.AccessToken)