响应状态代码不表示成功:401(未授权)- Azure Devops Feed ASP.NET Core 3.1 Docker Build
Response status code does not indicate success: 401 (Unauthorized) - Azure Devops Feed ASP.NET Core 3.1 Docker Build
我在这个论坛上发现了一些文章和 posts,涉及在使用 Docker 构建图像时无法授权 Azure 私有工件源的问题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 的构建参数文本框中我有这个:
NUGET_PAT=xxxxxxxxxxxxxxxxxxxxxxxxx
我还将 PAT 令牌设置为以下权限,如本论坛 post 中所述:
- 构建:阅读
- 已连接的服务器(访问端点):已连接的服务器
- 打包(创建、读取、更新和删除提要和包):阅读
我还设置了 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:
此解决方案基于使用构建过程中定义的变量动态构建 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"'
这是在 Azure 管道中为我工作的最终 Dockerfile
Docker build
和 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_FEED
和 NUGET_PAT
创建一个变量组,这样个人访问令牌和提要就可以在其他管道之间共享。
我在这个论坛上发现了一些文章和 posts,涉及在使用 Docker 构建图像时无法授权 Azure 私有工件源的问题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 的构建参数文本框中我有这个:
NUGET_PAT=xxxxxxxxxxxxxxxxxxxxxxxxx
我还将 PAT 令牌设置为以下权限,如本论坛 post 中所述:
- 构建:阅读
- 已连接的服务器(访问端点):已连接的服务器
- 打包(创建、读取、更新和删除提要和包):阅读
我还设置了 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:
此解决方案基于使用构建过程中定义的变量动态构建 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"'
这是在 Azure 管道中为我工作的最终 Dockerfile
Docker build
和 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_FEED
和 NUGET_PAT
创建一个变量组,这样个人访问令牌和提要就可以在其他管道之间共享。