# Pulling images from Azure Container Registry on GitLab CI How to use an image from Azure Container Registry as the base for GitLab Runner’s Docker executor. ## Using Service Principal Let's imagine we have image in ACR as follows `jigurda.azurecr.io/namaespace/awesome-toolbox:1.0.1`. This image is private and requires you to sign in to a private container registry. Let’s also assume that these are the sign-in credentials for your service principal: | Key | Example Value | |---------------|----------------------------------------| | registry | jigurda.azurecr.io | | client_id | 6394a177-82c1-4ce7-abe2-f6e92f3c5e76 | | client_secret | sTr0NgSecReT~etAmjI+JPF/aRPeHdRwicjhf | You can set the `DOCKER_AUTH_CONFIG` variable within your project’s `Settings` > `CI/CD` page: ```json "auths": { "jigurda.azurecr.io": { "auth": "bla-bla-bla" } } ``` You can add configuration for as many registries as you want, adding more registries to the `"auths"` hash as described above. The value of `auth` is base64-encoded version of your `client_id` and `client_secret` that you use to authenticate into the registry: ```bash echo -n "6394a177-82c1-4ce7-abe2-f6e92f3c5e76:sTr0NgSecReT~etAmjI+JPF/aRPeHdRwicjhf" | base64 ``` You can generate a JSON for `DOCKER_AUTH_CONFIG` variable using the following command: ```bash export CONTAINER_REGISTRY= export AZURE_CLIENT_ID= export AZURE_CLIENT_SECRET= PASSWORD_ENCODED=$(echo "${AZURE_CLIENT_ID}:${AZURE_CLIENT_SECRET}" | base64) jq -n --arg registry "${CONTAINER_REGISTRY}" --arg userpass "${PASSWORD_ENCODED}" '{auths: {($registry): {auth: $userpass}}}' ``` Now, add the DOCKER_AUTH_CONFIG variable to your project’s Settings > CI/CD page: ## Add `DOCKER_AUTH_CONFIG` variable from Gitlab job If you need to dynamically update the `DOCKER_AUTH_CONFIG` variable with a new password. Let's setup a new job for this ```yaml build:acr_auth: stage: build image: alpine:3.13 script: - export CONTAINER_REGISTRY=${PROJECT_CONTAINER_REGISTRY} - export AZURE_CLIENT_ID=${PROJECT_AZURE_CLIENT_ID} - export AZURE_CLIENT_SECRET=${PROJECT_AZURE_CLIENT_SECRET} # Your personal or project token with api access - export TOKEN=${PROJECT_API_TOKEN} - export PROJECT_ID=${CI_PROJECT_ID} - apk add --no-cache curl jq bash - chmod +x ./acr_auth.sh - bash ./acr_auth.sh ``` `acr_auth.sh` ```bash #!/bin/bash set -e GILBAL_CI_VARIABLE='DOCKER_AUTH_CONFIG' PASSWORD_ENCODED=$(echo "${AZURE_CLIENT_ID}:${AZURE_CLIENT_SECRET}" | base64) PAYLOAD=$(jq -n --arg registry "${CONTAINER_REGISTRY}" --arg userpass "${PASSWORD_ENCODED}" '{auths: {($registry): {auth: $userpass}}}') RESPONCE=$(curl --request GET --header "PRIVATE-TOKEN:$TOKEN" "$CI_API_V4_URL/projects/$PROJECT_ID/variables/$GILBAL_CI_VARIABLE" -s -o /dev/null -w "%{http_code}") if [[ "${RESPONCE}" == '404' ]]; then echo "Project level variable $GILBAL_CI_VARIABLE does not exist. Let's create it!" curl --request POST --header "PRIVATE-TOKEN:$TOKEN" "$CI_API_V4_URL/projects/$PROJECT_ID/variables" --form "key=$GILBAL_CI_VARIABLE" --form "value=$PAYLOAD" else echo "Update project level variable $GILBAL_CI_VARIABLE" curl --request PUT --header "PRIVATE-TOKEN:$TOKEN" "$CI_API_V4_URL/projects/$PROJECT_ID/variables/$GILBAL_CI_VARIABLE" --form "value=$PAYLOAD" fi ``` ## Access an image from Azure Container Registry with access_token from Gitlab job I doubt this will be useful to anyone, but I'll leave it here just in case. ```yaml build:acr_auth: stage: build image: docker:stable script: - export CONTAINER_REGISTRY=${PROJECT_CONTAINER_REGISTRY} - export AZURE_CLIENT_ID=${PROJECT_AZURE_CLIENT_ID} - export AZURE_CLIENT_SECRET=${PROJECT_AZURE_CLIENT_SECRET} - export AZURE_TENANT_ID=${PROJECT_AZURE_TENANT_ID} # Your personal or project token with api access - export TOKEN=${PROJECT_TOKEN} - export PROJECT_ID=${CI_PROJECT_ID} - apk add --no-cache curl jq bash - chmod +x ./acr_auth_token.sh - bash ./acr_auth_token.sh ``` `acr_auth_token.sh` ```bash #!/bin/sh set -e ACCESS_TOKEN=$(docker run --rm \ -e AZURE_CLIENT_ID=${AZURE_CLIENT_ID} \ -e AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET} \ -e AZURE_TENANT_ID=${AZURE_TENANT_ID} \ mcr.microsoft.com/azure-cli az login --service-principal -u ${AZURE_CLIENT_ID} -p ${AZURE_CLIENT_SECRET} -t ${AZURE_TENANT_ID} 1> /dev/null \ && az acr login -n ${CONTAINER_REGISTRY} --expose-token 2> /dev/null | jq -r '.accessToken' | base64) PASSWORD_ENCODED=$(echo "00000000-0000-0000-0000-000000000000:${ACCESS_TOKEN}" | base64) PAYLOAD=$(jq -n --arg registry "${CONTAINER_REGISTRY}" --arg userpass "${PASSWORD_ENCODED}" '{auths: {($registry): {auth: $userpass}}}') curl --request PUT --header "PRIVATE-TOKEN:$TOKEN" "${CI_API_V4_URL}/projects/${PROJECT_ID}/variables/DOCKER_AUTH_CONFIG" --form "value=${PAYLOAD}" ``` ## Related Links - [Authenticate with an Azure container registry](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-authentication?tabs=azure-cli) - [Azure Container Registry roles and permissions](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-roles?tabs=azure-cli) - [Determine your DOCKER_AUTH_CONFIG data](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#determine-your-docker_auth_config-data)