Pushing images to Docker Hub for multiple architectures (e.g. amd64, arm64) and pulling the correct one automatically
I'd recommend using BuildKit with buildx which is available in 19.03. First you probably want some setup on a Linux host using qemu and binfmt_misc for cross compiling. Without it, you would need a build node for each platform you want to build. With binfmt_misc, you need two important details to work inside of a container, first is you need the static user binaries, and second is the --fix-binary
flag needs to be used when injecting them into the kernel. For the first, that comes down to the package name you install, e.g. on Debian the package name is qemu-user-static. And for the second, this may require a version of the package from from an unstable release. E.g. here are a few bug reports to get the change included:
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=868030
- https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1815100
Once you've done this, you can verify the --fix-binary
result by looking for the F
flag in /proc/sys/fs/binfmt_misc/*
.
Next, you need to setup a buildx worker. That can be done with:
docker buildx create --driver docker-container --name local --use \ unix:///var/run/docker.sockdocker buildx inspect --bootstrap local
You should see something like the following from the inspect, note the multiple platforms:
$ docker buildx inspect --bootstrap local[+] Building 54.1s (1/1) FINISHED => [internal] booting buildkit 54.1s => => pulling image moby/buildkit:buildx-stable-1 45.4s => => creating container buildx_buildkit_local0 8.7sName: localDriver: docker-containerNodes:Name: local0Endpoint: unix:///var/run/docker.sockStatus: runningPlatforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
Now you can perform a build for multiple architectures. The $image_and_tag
must be an external registry where buildx can push the image. You cannot have a multi-arch image locally because docker images locally must be a single platform, but the registry like Docker Hub does support multi-arch manifests:
docker buildx build --platform linux/amd64,linux/arm64 \ --output type=registry -t $image_and_tag .
And you can even test those other images using the qemu cross platform support:
docker container run --platform linux/arm64 $image_and_tag
Note that you may need to enable experimental CLI options in docker, I forget which features have not made it to GA yet. In ~/.docker/config.json
, add:
{ "auths": { ... }, "experimental": "enabled"}
Or you can export a variable (adding to your .bashrc to make it persistent):
export DOCKER_CLI_EXPERIMENTAL=enabled
Note: docker desktop has included settings for qemu/binfmt_misc for a while, so you can skip straight to the buildx steps in that environment. Buildx can also be run as a standalone tool. See the repo for more details: https://github.com/docker/buildx