How to build multi-architecture docker images with buildx
Today we are going to discuss about how to build docker container images that can be deployed on system with multiple architecture. This has become more important today as the arm architecture has become an important part for developer machine and cloud based servers.
Multi-Architecture Manifest
We can run docker manifest inspect command in popular base images.
docker manifest inspect node
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2493,
"digest": "sha256:f5d08c5848bcd66a49fd521addedd1e2e6abeef597e3aa51a5c0a6cb340c3906",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 842,
"digest": "sha256:46f0bcbf54d0e99db7fbaf3bff1c675c3e0dc6c4b980ad56cd76fab744e6eab9",
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2495,
"digest": "sha256:8e0f1215e220f32b76e9426d615e753f4f0340740730e28601fe5da6a1294e14",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 842,
"digest": "sha256:c9b9457a73b354da6d22992a6504bcf80e5e24a8232e33432b1e2e5a8347f2fe",
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2495,
"digest": "sha256:c8cefed8be40e9591a39dde995e42b9689fde5acc69e875e89e7f3b259465c45",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 842,
"digest": "sha256:1f00bbf6b1eb4d69ea2d815d348e2c1dd4d2e2e402ec0f4f9f8106c293e69f4a",
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2495,
"digest": "sha256:238c31eca8cc1ccbbef8454fe8e22f8bd9c22a43c90ed8da46da634f6ff5c6cd",
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 842,
"digest": "sha256:225513e43ce579a0b791ebe853f49af0f27636bda44b96c5d6df2ed8d2ad0383",
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2493,
"digest": "sha256:8b775a10deff367e2b66ec5ede9a6469f066a66bd52d5730f8e28cb8e20a8af8",
"platform": {
"architecture": "s390x",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 842,
"digest": "sha256:7af00e6e0851adae35743ab7dd613e93159cffe8fafcb2c41315869781a48f3e",
"platform": {
"architecture": "unknown",
"os": "unknown"
}
}
]
}
Here the manifest output contains 3 separate manifest in manifest array each with different architecture.
Most official docker images support multiple architecture.
There are two ways of building these multi architecture docker images
The old way
You have to had system natively running architecture that you want to target. And you run the build command with separate docker file on those machine
docker build \
-f Dockerfile.x86 \
-t test-image:linux-x89 \
.
docker build \
-f Dockerfile.arm \
-t test-image:linux-arm \
.
Once they are build you can create a combine manifest
docker mainifest create test-image:tag \
test-image:linux-x86 \
test-image:linux-arm64
And this manifest is pushed to docker registry along with the images
docker manifest push test-image:tag
Docker Buildx
Buildx does number of things to build multi-architecture docker images.
- Treat native build nodes as build farm to build in parallel
- Using a single node with QEMU to emulate multiple architecture
We are going to focus on the second way, as it allows me to build multi-architecture docker images with one architecture machine. I have a x86 intel machine.
Now lets start building the multiple architecture docker image
- Lets login using the command below
docker login
- You can list the buildx in the system with command
docker buildx ls
- Now lets create a new buildx for the demo
docker buildx create --name testbuilder
- Now lets docker to use this new buildx
docker buildx use testbuilder
- Finally inspect the builder so make sure it works properly
docker buildx inspect testbuilder --bootstrap
- Now let build the docker images
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
-t docker_hub_user_name/image_name:image_tag \
--push \
.
- Now you can use this docker images and it should pull the appropriate architecture for the machine that you are using