I wrote two articles describing my experiments with BuildKit, one about low level set up for building cross-platform images by using emulation, BuildKit builder, and buildctl directly. And another one about using BuildKit as well but without an emulator and relying on
docker build command. The solution described in those articles is not ideal since you have to create platform-specific images one by one, push them to a Docker registry, create a multi-platform manifest, then push it as well, and, finally, delete the platform-specific tags.
Luckily enough, Docker 19.03 has buildx included in the package. Long story short, using
buildx and BuildKit you can not only build images for multiple platforms in parallel but also push multi-platform manifests alongside the images built to Docker Registry!
- Get the latest Docker (19.03 or later) and enable the experimental features.
- Log in to your Docker registry
- Create a
docker-containerdriver and set it to be the current builder.
docker buildx create --use
- Build and push multi-platform images and the manifest.
docker buildx build \ --progress=plain \ --platform="linux/amd64,linux/arm64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6" \ --tag foo/bar:1 --tag foo/bar:1.1 --tag foo/bar:1.1.1 -tag foo/bar:latest \ --push .
--progress=plain is used to avoid CI logs pollution.
This is basically it.
Please note that if you are not using RUN commands in the target platform part of your Docker file, you don’t need to register format recognizers. The emulator is not involved in such builds. But if you do, then make sure you do it before creating a BuildKit builder:
sudo docker run --privileged linuxkit/binfmt:v0.7
P.S. I created a Docker image with some bash scripts for simplifying multi-platform builds. Using those scripts you can update Docker, build and push a multi-platform image tagging it using a semantic tag, and push README file to Docker Hub. An example of using the scripts you can find here.