我有一个如下所示的 yaml Azure DevOps 管道,它正在尝试使用来自另一个组织的 nuget 提要。
如您所见,我正在使用 nugetauthenticate@1 任务使用目标组织中的用户创建的服务连接来创建有效凭据。
我有一个由管道调用的 docker 文件,在其中我通过它们的 sh 脚本安装工件凭证提供程序。
我正在 dockerfile 中设置 JSON 环境变量,并将有效的 PAT 传递到 docker 任务中:
arguments: '--build-arg FEED_ACCESSTOKEN=$(VSS_NUGET_ACCESSTOKEN)'
nb 我已尝试使用 cred 提供程序变量 $(VSS_NUGET_ACCESSTOKEN) 并使用包含有效 PAT 的我自己的管道变量。
当我在 docker 步骤中调用 dotnet restore 时,该步骤出现以下错误:
error NU1301: Unable to load the service index for source https://pkgs.dev.azure.com/{org}/_packaging/{feed}/nuget/v3/index.json
我已经打开了详细日志记录,并且凭据提供程序正在使用提供的配置,但我没有收到 Auth (401) 问题,只是在访问 nuget 索引页面 feed 时出现错误,所以我认为它甚至没有机会进行身份验证。
如有任何建议,我将不胜感激。
管道:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
NUGET.PLUGIN.HANDSHAKE.TIMEOUT.IN.SECONDS: 20
NUGET.PLUGIN.REQUEST.TIMEOUT.IN.SECONDS: 20
steps:
- task: NuGetAuthenticate@1
inputs:
nuGetServiceConnections: 'nuget-feed'
- task: NodeTool@0
inputs:
versionSpec: '18.17.1'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
arguments: 'xxx/xxx.sln'
- task: Docker@2
inputs:
command: 'build'
Dockerfile: 'xxx/xxx/Dockerfile'
buildContext: 'xxx'
arguments: '--build-arg FEED_ACCESSTOKEN=$(VSS_NUGET_ACCESSTOKEN)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
publishLocation: 'Container'
Docker 文件:
FROM mcr.microsoft.com/dotnet/aspnet:6.0.14-bullseye-slim-amd64 AS base
ARG FEED_ACCESSTOKEN
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0.427-1-bullseye-slim-amd64 AS build
ENV NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=60
ENV NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=60
RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | sh
WORKDIR /src
COPY ["xxx/xxx.csproj", "xxx/"]
COPY ["xxx/nuget.config", "xxx/"]
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS="{\"endpointCredentials\": [{\"endpoint\":\"https://pkgs.dev.azure.com/{org}/_packaging/{feed}/nuget/v3/index.json\", \"username\":\"docker\", \"password\":\"${FEED_ACCESSTOKEN}\"}]}"
RUN echo $VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
RUN dotnet restore "xxx/xxx.csproj" --verbosity detailed
我可以使用您共享的 Dockerfile 重现相同的错误。
查看日志后发现endpointCredentials命令中的密码为空,我添加了该命令
RUN echo "Access Token: $FEED_ACCESSTOKEN"
进行确认。在此之后,我将该行移至
ARG FEED_ACCESSTOKEN
之后FROM mcr.microsoft.com/dotnet/sdk:6.0.427-1-bullseye-slim-amd64 AS build
。新的 Dockerfile:
这次密码不为空,恢复步骤成功。
问题原因:
ARG
变量的作用域仅限于定义它们的阶段。因此,您应该将此行移至使用它的构建阶段。如果要在多阶段 Dockerfile 中共享变量,则每个阶段都必须包含该
ARG
指令。您可以参考此问题了解有关在多阶段 Dockerfile 中共享变量的更多信息。正如苗天的回答中所说,您需要将 ARG 移动到 dockerfile 中的正确代码块。
另外,Nuget Authentication 任务通过服务连接进行资源认证时,其输出变量:VSS_NUGET_ACCESSTOKEN并不是一个有效的 PAT/Password,因此无法直接用来设置 dockerfile 中的环境变量:VSS_NUGET_EXTERNAL_FEED_ENDPOINTS。
为了解决这个问题,你可以直接将 PAT 传递给 dockerfile(例如
--build-arg FEED_ACCESSTOKEN=$(YourPAT)
)或者您可以使用另一个输出变量:来自 Nuget Authenticate 任务的$(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)。
例如:
此变量是一个有效的 feed 工件端点,包含密码,可以直接传递给 Dockerfile 进行身份验证。
以下是一个例子:
Dockerfile:
由于存在已知问题:[BUG]:通过 docker 任务传递变量:VSS_NUGET_EXTERNAL_FEED_ENDPOINTS 时,Docker @2 参数(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)没有引号,我们需要改为使用脚本/bash/powershell 任务来运行 docker 命令来构建镜像。
管道示例:
在这种情况下,我们可以将凭证从服务连接传递给 dockerfile 进行 nuget feed 身份验证。
结果: