GitLab CI/CD pipelines can be used to automatically build and push Docker images to the GitLab Container Registry.
Beyond building a simple image, in this article I will show how to define a workflow that builds and pushes a multi-platform image (amd64,arm64,arm32) with manifest index to the GitLab Container Registry. This is enabled by using ‘docker buildx’ for the various target architectures.
Overview
We will be creating a GitLab pipeline by adding a yaml manifest with the standard name .gitlab-ci.yml into the root directory of our source repository. We will step through critical sections of this file below.
Pipeline
The ‘workflow‘ rules define when the pipeline will be run. The rules below say that the pipeline will be created at either a merge request, a push/tag, or when invoked from the GitLab web UI.
workflow: rules: # start workflow if merge request - if: $CI_PIPELINE_SOURCE == "merge_request_event" # start workflow if push/tag, or pipeline invoked from web UI - if: $CI_PIPELINE_SOURCE =~ /^(push|web)$/
Docker-in-Docker build task
As described in the GitLab documentation, the ‘dind’ (Docker in Docker) executor can be used to build container images.
build-and-push-image: stage: build image: docker:24.0.5 services: - docker:24.0.5-dind
Then in the ‘script’ section of this task, we perform the necessary steps for building multi-platform images.
script: | ... # login to GitLab Container Registry using pre-defined pipeline variables docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY # invoke tool that registers binfmt with QEMU for different architectures docker run --rm --privileged multiarch/qemu-user-static --reset -p yes # create builder with driver that supports multi-platform (default does not) docker buildx create --name mybuilder --driver docker-container docker buildx use mybuilder # build and push multi-platform image docker buildx build --output type=registry,oci-mediatypes=false --progress plain --platform $PLATFORMS_LIST -f Dockerfile -t $IMAGE_TAG_FULL --push --provenance=false . # show manifest index just generated docker manifest inspect $IMAGE_TAG_FULL
We used the buildx flag “–output type=registry,oci-mediatypes=false” to generate a Docker v2.2 manifest list. We could set the value to “true” and generate an OCI manifest index, but the GitLab UI will incorrectly display “Invalid tag: missing manifest digest”.
If you want further details on these steps, it may help to see my article where these steps are run manually for building multi-platform images.
GitLab pipeline invoked
This pipeline could be invoked by a simple push, but let’s do it by pushing a tag that looks like a semantic version so we can explicitly create an image version.
# check for any changes that might need to be checked in first git status # create new tag that triggers workflow, push tag newtag=v1.0.2 git tag $newtag && git push origin $newtag
This will almost immediately create a pipeline which you can view in real-time by going to your GitLab repository > Pipelines
You can view the real-time progress by clicking into the task. The icons will indicate when the workflow is complete.
GitLab Container Registry
From the GitLab web UI click on Deploy > Container Registry and each image version will be listed.
Validate multi-platform publish
The manifest index details can be seen by using ‘docker manifest index’.
docker manifest inspect registry.gitlab.com/gitlab-pipeline-helpers/tiny-tools-multi-arch:1.0.2 | head
Test a pull and run of the image by running docker like below.
# will output architecture family of running image docker run -it --rm registry.gitlab.com/gitlab-pipeline-helpers/tiny-tools-multi-arch:1.0.2 uname -m
REFERENCES
asksven.io, docker build for multiple architectures with buildx and GitLab pipeline
Juno Hill, gitlab project using buildx and GitLab pipeline for building multi-platform images
nithinbose.com, multiple architecture docker build with GitLab
gitlab issue, explaining why privileged reset flags needed for QEMU
nofusscomputing, image with docker buildx embedded
ix.ai gitlab, Dockerfile showing apt cleanup done for image with buildx
agrozyme, GitLab workflow include to handle buildx
gitlab issue, error with display of container images with gitlab web UI
fly.io, errors with latest docker buildx with Github Actions
GitLab docs, Docker-in-Docker builds
github moby, buildkit parameters