Multiplatform Images: Practical Guide
Have you ever wondered how Docker knows which image layer is required to run a container in your operating system? The answer is multiplatform images, and this piece walks you through the build process.
Let's start with a small demonstration. First, I run the uname command within the busybox image without indicating the platform. Kubernetes selected the optimal platform for my host operating system and ran the containers as Linux on ARM-64 bit.
The second time, I forced Docker to run the same command but with x86_64 architecture for the same image tag. It is possible because the busybox image supports the most common platforms.
Let's build our very own multiplatform image using the classic Docker Desktop. It should be modern enough to support the Buildx plugin (the Docker Engine 19.03 or higher is required). Windows and MacOS releases include the Buildx plugin; for Linux, you may want to install and configure it separately.
First, in the Docker General configuration, enable the option "Use containers for pulling and storing images." Save the changes, and Docker will restart the engine to apply the configuration update.
The next step is creating a new builder with the compatible driver, in our case, docker-container. The command below creates a new builder on your machine with the name containerd.
$ docker buildx create \
--name containerd --driver docker-container
Command ls lists all available builders in your system.
$ docker buildx ls
The same information you could find in the Docker Desktop interface
You could activate our new builder through the Docker UI (Click on ⋮ in the builder's row and select Use) or run the command from a terminal:
$ docker buildx use containerd
We are ready to build the first multiplatform image, starting with a minimalistic Dockerfile
Save the descriptor and build a new image with the command:
$ multi-platform % docker buildx build \
--platform linux/amd64,linux/arm/7,linux/arm64 \
-t my-mplatform:1.0 --load .
Some explanations for Buildx arguments:
- You should specify multiple platforms with a --platform argument. I requested the standard x86_64 Linx and two ARM-compatible platforms.
- The main difference between docker and docker-container drivers is that the latest does not load images into the local repository by default. To make the image available locally, use the --load argument; if you are ready to push it to the remote repository, you should add --push.
The screenshot below demonstrates that our new build supports multiple CPU architectures.
More information is available on the official Docker site. Plus, Podman supports multiplatform builds and could be a viable alternative, especially for automated CI/CD pipelines.