- Docker
- Azure
- Azure DevOps
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.
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.
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"
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.
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!