Docker build multiarch image

February 24, 2025

Lang: cs en de es

If you use Docker on a RaspberryPi or Mac, you will find that not all Docker images will always run there. I'll describe how to solve this with a multi-platform image in this article.

The reason why you can't run the container on a Raspberry PI or Mack is that these devices have a processor with ARM architecture, which is a different architecture than the x86-64 on regular PCs. One way to address this is to do a build image locally on the device. But you would have to perform the build every time on every device. Better to create a so-called multiarch build, where you create a docker image that is for multiple CPU architectures.
You create such an image only once and upload it to image registry on Docker hub or GitLab. And everyone else with a PC, RaspberryPI and Mac will then download the finished image for their CPU architecture and run the container from it if needed. So they won't have to do the build image locally on their machine. Assuming of course that the build is done for their CPU as well.

Nowadays it is common that all base images are built for x86-64 and ARM.

What is a Docker image from a technical point of view? And typically it's all opensource software. Thanks to that, such software runs on many types of architectures. Such software also runs on many operating systems.
We're talking about Docker and those are Linux containers. And those can only run on Linux, even if it's a Linux virtual machine running on Windows or a Mac.
Of course your private Docker image contains what you put in there. So for example also proprietary software and there independence on OS, Linux distribution and CPU architecture is purely up to you. So if you have not taken this into account, it may happen that without further modifications your software will not run on a computer with an ARM CPU.

The Docker documentation uses the term multi-platform build and I prefer to use the term multi-arch build.

Today, image/containers of the OCI standard are used and these have multi-platform build support. Once upon a time docker did not use this standard, so don't expect to be able to use multi-platform build on old systems.

Where you will see ARM CPUs

When you typically have to deal with using a multi-platform build:

  • Your developers are using Apple Macs, which in new releases have an ARM CPU.
  • You want to optimize costs in AWS so you have decided to use a VPS with an ARM CPU.
  • You want to buy new modern servers with ARM CPUs e.g. HP proliant.

Two Ways

The build configuration, the Dockerfile, remains unchanged.
There are two ways to make a multi platform build docker image:

  1. Use BuildX and do something like cross build.
  2. Do a build on a given platform and then combine it in a multi arch image.

BuildX

Buildx is a Docker extension that provides advanced functionality for building containers. It is part of the Docker CLI and allows you to build images using BuildKit, which is a modern Docker build system with improved performance and flexibility.

One of the key features of buildx is support for multi-platform builds. So it can build images for different architectures (e.g. linux/amd64, linux/arm64). However, in some cases, due to emulation, such a build for a different architecture can be very slow.

By default the Linux distribution Mageia or Debian does not use buildX, so by default it does not support cross-platform builds.

Building BuildX

Verify Docker version - Multi-platform support was only brought to Docker version 19.03 and later. Check your version with the command:

docker --version
docker buildx version

Installing buildX on a Mageia distribution
urpmi docker-buildx

Installing buildX on a debian Linux distribution, including the docker itself:

curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Configure docker to use buildX and be able to build for amd64 and arm64 architectures

docker buildx create --use

To list the builders available, use the command:

docker buildx ls
Set buildx as the default builder for docker:
docker buildx use default
The following command removes the specified buildx builder.
docker buildx rm builder_name

Build image

To run build image for arm64, for example, use this command:

docker buildx build --platform linux/arm64 .

Build for two architectures at the same time:

docker buildx build --platform=linux/amd64,linux/arm64 .

Standard build and subsequent connections

If you need to solve a build image for some other architecture, you typically have such an architecture available. Then a quick and easy implementation is to perform a build on each architecture to perform a push image and then merge that into a multi-platform image.
It's a process where you don't have to modify the docker configuration in any way and the build is very fast. It's also fast because the build is done natively without emulating another processor architecture.

Build image for AMD64 on x86 PC:

docker build ./ -t josefjebavy/debian-apache-php-test:amd64
docker push josefjebavy/debian-apache-php-test:amd64

Build image for ARM64 e.g. on RaspberryPI:

docker build ./ -t josefjebavy/debian-apache-php-test:arm64
docker push josefjebavy/debian-apache-php-test:arm64

Creating a manivest for AMD64 imge and for ARM64 image:

docker manifest annotate josefjebavy/debian-apache-php-test:latest josefjebavy/debian-apache-php-test:amd64 --os linux --arch amd64
docker manifest annotate josefjebavy/debian-apache-php-test:latest josefjebavy/debian-apache-php-test:arm64 --os linux --arch arm64

Creating a manifest for the master image that links the image to specific architectures:

docker manifest create josefjebavy/debian-apache-php-test:latest \
   --amend josefjebavy/debian-apache-php-test:amd64 --amend josefjebavy/debian-apache-php-test:arm64

Pushing the manifest to the docker registry:

docker manifest push josefjebavy/debian-apache-php-test:latest
The resulting multi-paltform image can be viewed here: https://hub.docker.com/r/josefjebavy/debian-apache-php-test and even download and test it. For example, by running in Docker with the command
docker run -p 80:80 -it --rm --name www --env="VAR=loremimpus" josefjebavy/webapp-test:latest
or Kuberteness. From this image you will be able to run the container on both x86_64 PCs there on ARM.

Video sample

Video demonstration of how to create an image in dockerhub that will be for x86_64 and for ARM.

Links

Articles on a similar topic

VMware vs Proxmox: performance comparison
GitLab CI/CD: test automation and application deployment
Migrating VPS from VMware to Proxmox
VMware licensing change
Running Microsoft SQL Server on Linux
Backup: the Proxmox Backup Server
Linux as a router and firewall
How to upload a docker image to the Docker Registry
Linux: logical volume management
Linux Software RAID
Running a web application behind a proxy
Mailbox migration
Docker multistage build
Backing up your data by turning on your computer
Podman
Importing Windows into Proxmox virtualization
Docker and PHP mail
Proxmox virtualization
Docker and Cron
Lenovo ThinkPad X1 Carbon: LTE modem EM7544 commissioning
Yocto Project: Build custom operating system for embedded devices
Preparing a Linux server to run a web application in Python
How to address poor file share performance in Docker
How to get started using Docker correctly
Installing Linux on a dedicated HPE ProLiant DL320e server
How to stress test a web application
Why use the JFS filesystem
How to boot from a 4TB drive with GTP using UEFI
Btrfs file system
Raspberry PI
WINE - running Windous programs under Linux
GNU/Linux operating system

Newsletter

If you are interested in receiving occasional news by email.
You can register by filling in your email news subscription.


+