Accessing Azure Artifacts from a docker container in a Pipelines build

January 17, 2019
[ azure  azure-devops  pipelines  nuget  artifacts  docker  ]

_config.yml

In my previous post I talked about how our team is publishing NuGet packages using Azure Pipelines to a DevOps Artifacts feed. Now it’s time to consume those packages. There are plenty of examples on how to connect to a feed in Build, but our case is a bit different because our applications are containerized. The purpose of this post is to share specifically how we authorize access to Artifacts from a docker build context in an Azure DevOps Build.

Please see this Gist for full code references.

Security

The purpose of using Azure Artifacts is to avoid a public package manager because the team is writing IP into shared libraries. It should then come as no surprise that there are a few additional steps required to ensure that your docker build context has appropriate access to Azure DevOps.

The docker build context is isolated from Azure DevOps, meaning that it should be considered a sandboxed build that doesn’t share environment variables and access that typical Build tasks would. The trick to authorizing a docker build is to use a Personal Access Token as a rotatable key that tells Azure DevOps that it is authorized to pull packages from Artifacts. Start by creating a PAT: click your avatar in the upper right of DevOps then Security in the dropdown. Make sure it has access to Packaging.

Pipelines variable group

The next step is to create a group of variables that you can share between all Build definitions. I created an Artifacts group and added an artifactsAccessToken (this is your Private Access Token) and artifactsEndpoint which I got from clicking Connect to Feed from my Artifacts feed.

_config.yml

CI and CD builds

Go ahead and create your CI and CD builds and feel free to use my files as a template. Note that I am specifically passing in the variables I created in the variable group above using the following method:

...

variables:
- group: Artifacts

...

steps:
- task: Docker@1
  displayName: 'Build an image'
  inputs:
    ...
    arguments: '--build-arg ARTIFACTS_ENDPOINT=$(artifactsEndpoint) --build-arg ACCESS_TOKEN=$(artifactsAccessToken)'

This ensures that the variables get mapped to the Dockerfile ARGS that we also need to define.

Important: once you create the build in DevOps, you need to click through Variables > Variable groups and click Link variable group. This is a security feature and is a required step.

_config.yml

Dockerfile

Now that we have builds set up, create a Dockerfile that defines how your app is build and run. To use the variables we passed in via Build above, create ACCESS_TOKEN and ARTIFACTS_ENDPOINT ARGS to accept them. The key changes from a typical Dockerfile is that you need to install the Azure Artifacts Credential Provider and then set the NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED and VSS_NUGET_EXTERNAL_FEED_ENDPOINTS environment variables to let it do its job. Also, alter your dotnet restore task to use the new feed endpoint.

Now run through the entire process and make sure everything works correctly. If so, you should have a new docker container image ready for deployment! Please reach out if you have any questions or a different approach.

Share this post!