ARG PAT RUN wget -qO- https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | bash ENV NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED true ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS “{\”endpointCredentials\”: [{\”endpoint\”:\”https://pkgs.dev.azure.com/jakob/_packaging/DockerBuilds/nuget/v3/index.json\”, \”password\”:\”${PAT}\”}]}”
The technique is to install the credential provider, then configure it with the DevOps Artifacts endpoint and a Personal Access Token (PAT), which you can generate by going to your user settings from the DevOps UI:
After wasting over a day on this, I was then very surprised indeed to find that a colleague was restoring from the same DevOps Artifacts feed on a locally hosted TeamCity server, simply by providing the PAT as the NuGet API-Key! They hadn't installed the NuGet credential provider, so according to the Microsoft documentation it shouldn't work?
I tried it myself. The PAT does indeed work as a NuGet API-Key. A slight further complication is that the 'dotnet restore' command doesn't have an API-Key switch, so the next easiest thing is to simply use a nuget.config file as follows:
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="DevOpsArtifactsFeed" value="your-devops-artifacts-nuget-source-URL" /> </packageSources> <packageSourceCredentials> <DevOpsArtifactsFeed> <add key="Username" value="foo" /> <add key="ClearTextPassword" value="your-PAT" /> </DevOpsArtifactsFeed> </packageSourceCredentials> </configuration>
Replace the place-holders with your Artifacts NuGet feed URL and your PAT. The Username is not considered by Artifacts feed and can be any string. Copy the above configuration into a file named 'nuget.config' and run create a Dockerfile like this:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build WORKDIR /app # copy source code, nuget.config file should be placed in the 'src' directory for this to work. COPY src/ . # restore nuget packages RUN dotnet restore --configfile nuget.config # build RUN dotnet build # publish RUN dotnet publish -o output # build runtime image FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS runtime WORKDIR /app COPY --from=build /app/output/ ./ # ENTRYPOINT ["your/entry/point"]
This is the simplest thing that will possibly work. But you really shouldn't hard code secrets such as your PAT into your source control system. Very conveniently, the dotnet restore command will do environment variable replacement in the nuget.config file, so you can replace your hard-coded PAT with a reference to an ENV var and then pass that to docker build:
In your nuget.config file:
<packageSourceCredentials> <DevOpsArtifactsFeed> <add key="Username" value="foo" /> <add key="ClearTextPassword" value="%NUGET_PAT%" /> </DevOpsArtifactsFeed> </packageSourceCredentials>
In your Dockerfile:
ARG NUGET_PAT ENV NUGET_PAT=$NUGET_PAT
Your docker build command:
docker build -t my-image --build-arg NUGET_PAT="your PAT" .
I hope this short post saves somebody from the many hours that I wasted on this. I also hope that Microsoft updates their documentation!
Have been bitten by this before, and came up with much crapper solution to this, where I pre-published stuff and then copied the result of the publish to the new layer for container
ReplyDeleteAnyway great post, have added my own link here to it : https://sachabarbs.wordpress.com/2020/08/04/restoring-from-an-azure-artifacts-nuget-feed-from-inside-a-docker-build/