Generating Multi-Architecture Docker Images Made Easy

Docker has become my favorite virtualization technique. It provides a high level of abstraction with clear interfaces.

Docker is cool and portable, so creating your own Docker images is tempting. The user can get at your Docker image in two ways:

Creating Multi-Arch Docker Images

So here is a simple recipe:

  1. Make sure your host can execute binaries for all kinds of architectures:
    docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
    This uses a Docker image to tell Linux that it can run 29 additional CPU architectures. Of course, this comes at a cost: Emulation using QEMU. This means, things will run much slower. But hey, they will run at all!
    This is the precondition for building Docker images for a different architecture.
  2. Install buildx, the Docker build extension:
    Download the buildx for your CPU from and save it as ~/.docker/cli-plugins/docker-buildx.
  3. Create a multi-architecture builder:
    docker buildx create --name docker-multiarch && docker buildx inspect --builder docker-multiarch --bootstrap
  4. Build your multi-architecture Docker Image!
    docker buildx build --builder docker-multiarch --platform linux/amd64,linux/386,linux/arm64,linux/arm/v6 <your-docker-dir>

This gives you Docker images for the named --platforms. Of course, your selection might differ, but my use case, the Zeitgitter timestamping server, I believe that Intel/AMD servers and Raspberry Pis will be the main deployment platforms.

That’s not all, folks!

However, having the images built inside the docker-multiarch container is not going all the way. You need to make it available, either locally, or in a Docker repository. If you want to do the latter, add --push -t <repository-name> to the command line. But now, that’s really all, folks!

Automating the process: Makefile

The following excerpt from a Makefile shows how to automate this: [Updated 2023-10-10: Support pre-packaged buildx as well]

# Modify these according to your needs
PLATFORMS = linux/amd64,linux/arm64,linux/arm/v6
TAG       = zeitgitter/zeitgitter
DOCKERDIR = zeitgitter

# This probably should remain as is
BUILDXDETECT1 = ${HOME}/.docker/cli-plugins/docker-buildx
BUILDXDETECT2 = /usr/libexec/docker/cli-plugins/docker-buildx

.PHONY: qemu buildx docker-multiarch-builder

docker-multiarch: qemu buildx docker-multiarch-builder
	docker buildx build --pull --push --platform ${PLATFORMS} -t ${TAG} ${DOCKERDIR} 

qemu:	/proc/sys/fs/binfmt_misc/qemu-m68k
	docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

	@if [ ! -x ${BUILDXDETECT1} -a ! -x ${BUILDXDETECT2} ]; then \
		echo '*** `docker buildx` missing. See ``'; \
		exit 1; \

docker-multiarch-builder: qemu buildx
	if ! docker buildx ls | grep -w docker-multiarch > /dev/null; then docker buildx create --name docker-multiarch && docker buildx inspect --builder docker-multiarch --bootstrap; fi

Yes, the process of downloading and installing buildx could also be automated, but it isn’t as easily reversible, so I leave it to the user. The entire Makefile can be found here.

Happy Multi-Architecture Coding!

The fine print

I learnt a lot from these writeups:

If you would like to have more insight into what happens or how to go on even further, you will find a lot of information in the above articles.

I also borrowed from the original Docker image and have seen a similar design to what I made from it, but fail to remember where I found it. If anyone has a clue, please remind me, so I can credit the idea.

Let’s stay in touch!

Receive a mail whenever I publish a new post.

About 1-2 Mails per month, no Spam.

Follow me on the Fediverse

Web apps

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.