How to Build a Multi-Arch Image in GitLab CI
A single buildx job in GitLab CI can emit both amd64 and arm64 layers behind one image tag.
Register QEMU, create a buildx builder, then build for both platforms and push a combined manifest. The dind service gives you a Docker daemon to talk to.
Buildx with the dind service
Use the docker:dind service so buildx has a daemon, then build for two platforms in one step.
.gitlab-ci.yml
build-image:
image: docker:24
services:
- docker:24-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker run --privileged --rm tonistiigi/binfmt --install all
- docker buildx create --use --name multi
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
- docker buildx build --platform linux/amd64,linux/arm64 -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" --push .Notes
- binfmt registers the emulators so arm64 builds run on an amd64 runner.
- The --push flag is required because a multi-platform result cannot be loaded into the local daemon.
- Native arm64 runners avoid QEMU and are far faster; teams that want managed amd64 and arm64 runners without maintaining dind can migrate to GitHub Actions on Latchkey.