Photo by Stefan Steinbauer

How to use secrets inside your Docker build using Azure DevOps

Use secrets in your Dockerfiles

Posted by Damien Aicheh on 08/15/2022 · 5 mins

When you build a Docker image you often need to use secrets to be able to retrieve some dependencies. To download them, you must pass credentials inside your Dockerfile. But how to do it properly?

In this tutorial you will see how to pass credentials inside your Azure DevOps pipeline into your Dockerfile to build a Docker image successfully.

Use case

Let’s imagine you have to build a dotnet project but you have some nugets package stored in the Azure DevOps artifacts section. The Dockerfile to build the project should look something like this:

FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal AS base
WORKDIR /app

ENV ASPNETCORE_URLS=http://+:5100

# Creates a non-root user with an explicit UID and adds permission to access the /app folder
# For more info, please refer to https://aka.ms/vscode-docker-dotnet-configure-containers
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

FROM mcr.microsoft.com/dotnet/sdk:6.0-focal AS build

COPY ["src/DemoProject/DemoProject.csproj", "src/DemoProject/"]

## Restore section
RUN dotnet restore "src/DemoProject/DemoProject.csproj" 

COPY ./src ./src
WORKDIR "/src/DemoProject"
RUN dotnet publish "DemoProject.csproj" -c Release --no-restore -o /app/publish

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

When Docker will start to run the restore command it will failed, because to access the nugets packages inside Azure DevOps artifacts from the Dockerfile, you must add a new nuget source. But to add a new nuget source you need to provide a Personal Access Token (PAT) to authenticate.

Declare a secret inside a Dockerfile

To pass a secret properly you need to use Docker BuildKit. It’s really easy, you mount the secret with an identifier: id and a destination: dst, both can be the same.

So in our use case we mount the AZURE_DEVOPS_PAT that will contain the Personal Access Token for Azure DevOps:

--mount=type=secret,id=AZURE_DEVOPS_PAT,dst=/AZURE_DEVOPS_PAT

Then we can add a new nuget source with the AZURE_DEVOPS_PAT as password:

dotnet nuget add source --username USERNAME --password `cat /AZURE_DEVOPS_PAT` --store-password-in-clear-text --name common_nugets "https://pkgs.dev.azure.com/<YOUR-ORGANISATION-NUGET-FEED>/index.json"

So the restore command will be:

RUN --mount=type=secret,id=AZURE_DEVOPS_PAT,dst=/AZURE_DEVOPS_PAT \
    dotnet nuget add source --username USERNAME --password `cat /AZURE_DEVOPS_PAT` --store-password-in-clear-text --name common_nugets "https://pkgs.dev.azure.com/<YOUR-ORGANISATION-NUGET-FEED>/index.json" && \
    dotnet restore "src/Project/Project.csproj" 

Build the Docker image

Now, you have the Dockerfile correctly configured, let’s see how to build the image inside Azure DevOps.

To build the image you can use the Bash@3 task and run this command:

- task: Bash@3
  displayName: Docker build image
  inputs:
    targetType: inline
    script: |
      docker build \
      --secret id=AZURE_DEVOPS_PAT \
      -t $<YOUR_ACR_LOGIN_URL>/<YOUR_DOCKER_IMAGE>:<YOUR_DOCKER_TAG> .
  env:
    AZURE_DEVOPS_PAT: <VALUE_FROM_YOUR_AZURE_DEVOPS_SECRETS>
    DOCKER_BUILDKIT: 1

Multiple things are important to note above:

  • You need to define an env variable AZURE_DEVOPS_PAT and assign the correct value to it. Make sure to store the PAT in a secure variable inside a variables group of Azure DevOps. If you are not familiar with variables groups you can look at my previous tutorial about it.

  • You define the secret id with the same environment variable AZURE_DEVOPS_PAT like this: --secret id=AZURE_DEVOPS_PAT.

  • To be able to mount secrets in Docker with Docker BuildKit you must set the DOCKER_BUILDKIT env variable to 1 to activate it.

Final touch

Now you know how to properly pass your secrets into your Dockerfile using Azure DevOps. Of course you can pass as many secrets as you need.

Happy coding!

Do not hesitate to follow me on to not miss my next tutorial!