Introduction
My previous article described how to access a Google Container Registry from Kubernetes or Docker.
This short tutorial shows how you can configure Gitlab CI to authenticate and push docker images to a Google Container Registry.
Step 1 - Base64 encode your GCP Service Account key
When creating environment variables in Gitlab you can optionally mask them from the job logs (recommended for sensitive variables). However masked variables must meet a set of requirements in order to be considered valid. Base64 encode your Service Account key with the following command to meet those requirements.
base64 -w0 ~/key.json > ~/key-base64.json
(the -w0
option ensures the encoded output is formatted as a single line)
Step 2 - Create an environment variable in your Gitlab project
Navigate to Settings > CI/CD in your project (or Group) and expand the Variables section. Click on Add Variable.
Note: Variables created in a Group are inherited by and available to all projects in said group.
Name your Key (e.g. GCP_SA_KEY) and paste the contents of your base64 encoded Service Account key from the previous step into the Value field. Be sure to select ‘File’ as the variable Type. Check the Mask variable option (and the Protect variable option too if you require it). Click on Add variable to finish adding the variable to your project.
Step 3 - Configure .gitlab-ci.yml file to use the Service Account variable
To login to the GCR, first decode the Service Account variable (base64 -d
) and pass it to --password-stdin
in the docker login
command
base64 -d $GCP_SA_KEY | docker login -u _json_key --password-stdin https://gcr.io
At the build
stage, tag the image with the correct GCR name format (*.gcr.io/PROJECT_ID/IMAGE_PATH:TAG
)
docker build --cache-from -t gcr.io/[PROJECT_ID]/[IMAGE_PATH]/[IMAGE_NAME]:[IMAGE_TAG] .
Example
docker build --cache-from -t gcr.io/arctic-goal-676703/colinwilson/test_image:1.0 .
Note: Don’t forget the period at the end, it’s easy to miss.
Push the image to the GCR
docker push gcr.io/[PROJECT_ID]/[IMAGE_PATH]/[IMAGE_NAME]:[IMAGE_TAG]
Example
docker push gcr.io/arctic-goal-676703/colinwilson/test_image:1.0
Here’s the final.gitlab-ci.yml
configuration file. The example configuration below builds and pushes an image to both Google and Gitlab container registries.
image: docker:latest
services:
- docker:dind
stages:
- build
before_script:
# Login to Google Container Registry
- base64 -d $GCP_SA_KEY | docker login -u _json_key --password-stdin https://gcr.io
# Login to Gitlab container Registry
- echo $CI_JOB_TOKEN | docker login -u gitlab-ci-token $CI_REGISTRY --password-stdin
build:
stage: build
script:
# Build and tag image for both GCR and Gitlab registries
- docker build --cache-from -t gcr.io/$PROJECT_ID/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:latest -t $CI_REGISTRY_IMAGE:latest .
# Push image to GCR
- docker push gcr.io/$PROJECT_ID/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:latest
# Push image to Gitlab registry
- docker push $CI_REGISTRY_IMAGE:latest
Note: In the above example I’ve used additional variables (set in Gitlab) in place of hard coded values. e.g. $PROJECT_ID / $CI_PROJECT_NAMESPACE / $CI_PROJECT_NAME