Pushing images to Docker Hub for multiple architectures (e.g. amd64, arm64) and pulling the correct one automatically Pushing images to Docker Hub for multiple architectures (e.g. amd64, arm64) and pulling the correct one automatically docker docker

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:

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