响应状态代码不表示成功:401未经授权-Azure Devops Feed ASP.NET Core 3.1 Docker Build

问题描述

我在该论坛上找到了一些文章和帖子,这些文章和有关在Azure中使用Docker构建任务构建映像时无法被授权的Azure私有工件提要的问题有关,这是可以理解的。

因此,我整理了一个Dockerfile来反映在线示例:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
workdir /app

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
workdir /src

EXPOSE 80

# The Personal Access Token arg
ARG NUGET_PAT

# Set environment variables
ENV NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED true
ENV VSS_NUGET_EXTERNAL_Feed_ENDPOINTS '{"endpointCredentials": [{"endpoint":"https://pkgs.dev.azure.com/MY_Feed/nuget/v3/index.json","username":"username","password":"${NUGET_PAT}"}]}'

# install wget
RUN apt-get update && apt-get install -y wget 

# Get and install the Artifact Credential provider
RUN wget -O - https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh  | bash

copY ["xxx.csproj","."]
RUN dotnet restore -s "https://pkgs.dev.azure.com/MY_Feed/nuget/v3/index.json" -s "https://api.nuget.org/v3/index.json"

copY . .
workdir "/src"
RUN dotnet build "xxx.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "xxx.csproj" -c Release -o /app/publish

FROM base AS final
workdir /app
copY --from=publish /app/publish .
ENTRYPOINT ["dotnet","xxx.dll"] 

然后在Azure的build args文本框中,我有这个:

NUGET_PAT=xxxxxxxxxxxxxxxxxxxxxxxxx

我也已将PAT令牌设置为以下权限,如该论坛上的帖子中所述:

  • 构建:阅读
  • 已连接的服务器(访问端点):已连接的服务器
  • 包装(创建,读取,更新和删除摘要和包):阅读

我还将PAT设置为允许所有组织(而不是我们的工作组)使用,并且我尝试将nuget.config直接复制到容器中,最后得到的是未经授权的401

我还把username设置为“用户名”,因为大多数示例都提到它不是必需的。

我在做什么错了?

解决方法

您可以尝试以下格式以查看其是否有效:

ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS "{\"endpointCredentials\": [{\"endpoint\":\"https://pkgs.dev.azure.com/org/_packaging/MY_FEED/nuget/v3/index.json\",\"password\":\"${NUGET_PAT}\"}]}"

还有另一种方法可以尝试,请查看以下博客以获取解决方案2:

https://medium.com/jtorrecilla-net/use-azure-artifacts-in-dotnet-restore-while-docker-build-7e017a439109

此解决方案基于动态使用消耗在构建过程中定义的变量的情况下构建Nuget.Config文件。例如:

Docker文件:

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM microsoft/dotnet:2.2-sdk AS build
ARG ARTIFACTS_ENDPOINT
ARG ACCESS_TOKEN
ARG USER
WORKDIR /src
COPY / /src/Services/MyApi/
WORKDIR /src/Services/MyApi/
RUN echo "<?xml version='1.0' encoding='utf-8'?><configuration><packageSources><add key='MyFeed' value='$ARTIFACTS_ENDPOINT' /></packageSources><packageSourceCredentials><ByThey><add key='Username' value='$USER' /><add key='ClearTextPassword' value='$ACCESS_TOKEN' /></ByThey></packageSourceCredentials></configuration>" > NuGet.Config
RUN dotnet restore MyApi.csproj -nowarn:msb3202,nu1503

FROM build AS publish
RUN dotnet build MyApi.csproj --no-restore -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet","MyApi.dll"]

CI yml文件:

variables:
- group: Artifacts
steps:
- task: Docker@1
  displayName: 'Build an image'
  inputs:
    command: Build an image
    azureSubscription: Devops
    azureContainerRegistry: '{"loginServer":"xxx.azurecr.io","id" : "/subscriptions/xxx/resourceGroups/xxx-DEV/providers/Microsoft.ContainerRegistry/registries/xxx"}'
    dockerFile: src/Services/MyApi/Dockerfile
    imageName: $(Build.Repository.Name):$(Build.BuildId)
    arguments: '--build-arg ARTIFACTS_ENDPOINT="$(artifactsEndpoint)" --build-arg ACCESS_TOKEN="$(artifactsAccessToken)" --build-arg USER="xxx"'
,

这是在Docker Dockerfilebuild任务下在Azure管道中对我有用的最终push

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src

EXPOSE 80

# run the azure credential provider and let it do its magic
RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh  | sh

# personal access token arg 
ARG NUGET_PAT

# link to azure feed arg
ARG AZURE_FEED

# set env var for azure credential provider
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS \
    "{\"endpointCredentials\": [{\"endpoint\":\"${AZURE_FEED}\",\"username\":\"docker\",\"password\":\"${NUGET_PAT}\"}]}"

# debug env vars to make sure things are getting set correctly
RUN printenv

# restore private and public nuget feed
COPY ["xxx.csproj","."]
RUN dotnet restore -s "${AZURE_FEED}" -s "https://api.nuget.org/v3/index.json"

# build
COPY . .
WORKDIR "/src"
RUN dotnet build "xxx.csproj" -c Release -o /app/build

# publish
FROM build AS publish
RUN dotnet publish "xxx.csproj" -c Release -o /app/publish

# run
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet","xxx.dll"]

我还发现最好在Azure中使用AZURE_FEEDNUGET_PAT创建一个变量组,以便可以在其他管道之间共享个人访问令牌和源。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...