How to retag multi architecture container images
The problem
We build a container image on a feature branch with a commit SHA tag, something like this lansible/application:c1ee81ad5d18fcecfa4af5c97b853a4121875664
After the feature branch is merged we don’t want to rebuild the image, that could result in a different image going to production since there is no guarantee that the rebuild is 100% identical. Also skipping the rebuild saves a lot of CI time and therefore waiting. So currently after a fast-forward merge to main we retag SHA hash image to a production release:
docker tag \
lansible/application:c1ee81ad5d18fcecfa4af5c97b853a4121875664 \
lansible/application:1.0.0
This works perfect when you just build for one architecture. Since Apple is switching to arm64
for their new CPUs there is
a need to build multi-architecture images since the QEMU emulation of Docker on MacOS is slow and has segfault issues once in a while.
The solution
The easy part: Docker builds with buildx
This step was the easiest since docker/buildx makes building for multiple architectures a breeze.
First you need to setup QEMU emulation for the architectures you are missing. I use tonistiigi/binfmt for this. tonistiigi is not a random Github user, he is part of Docker and a big contributor on the docker/buildx repository.
Then you need to register a new context for buildx to take advantages of these new architectures:
Now you are ready to build multi-archicture images with buildx and the build
command (docs):
Even an existing docker-compose.yml
with multiple images is easy to convert to multi-architecture build with the bake
command (docs):
The following command will build all the containers in the compose file for amd64 and arm64 without adding the platforms explicitly in the compose files.
The hard part: Retagging the multi-architecture image
Since there is now a manifest under the SHA tag and not just one image the docker tag
command does not work to retag the image.
I tried using buildx imagetools create
(docs) but I couldn’t get it to work:
The error doesn’t get much hits on Google and whatever I tried I couldn’t get it to work. But in the search I stumbled upon regclient/regclient/ and the regctl
command which has an image copy
that seems to do exactly what I wanted (docs).
So I rewrote the docker tag
from above to this:
And we have achieved the retagging like before with docker tag
except now with the multi-architecture manifest still intact and pointing to the correct images. regctl
also is smart and doesn’t need to pull the image most of the times!