How to create multiarch docker images.

How to create multiarch docker images.

If you are like me and you need to create some kubernetes integration I prefer to have it done locally without too much fuss and for that I am mostly using raspberry pi's to create either standalone docker server or create a kubernetes cluster and have it running on that before you put it on staging/testing or even production. The downside of that it is that raspberry pi's are not using the same architecture as your destination staging/testing/production servers are. Therefore you need to have the ability to create container images that supports multiarchitectures. Having that said let's jump into it. All you need to do is to have the 2.0.4.0 (33772)+ version of Docker desktop or docker 20.x of docker server running as these versions come with buildx cli command that is allowing you to have locally build multiarchitectural version of the images.
By default we are using the default builder that is the old docker builder. In order to have the multiarchitectural build availability we need to createa a new builder.

#docker buildx ls
NAME/NODE    DRIVER/ENDPOINT             STATUS  PLATFORMS
default      docker                              
  default *  default                     running linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

To create a new builder we need to run the following:

#docker buildx create --name <name of a builder> --platform=linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7,...
<name of a builder>

To activate it you need to run the following:

#docker buildx use <name of a builder>

You can check it by running the following command:

#docker buildx ls
NAME/NODE    DRIVER/ENDPOINT             STATUS   PLATFORMS
test *       docker-container                     
  test0      unix:///var/run/docker.sock inactive 
default      docker                               
  default    default                     running  linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

In order to start the docker container that will be the builder of our new images I will be inspecting the builder with --bootstrap option

#docker buildx inspect --bootstrap
[+] Building 9.8s (1/1) FINISHED                                                                                                                                                                                                            
 => [internal] booting buildkit                                                                                                                                                                                                            9.7s
 => => pulling image moby/buildkit:buildx-stable-1                                                                                                                                                                                     8.1s
 => => creating container buildx_buildkit_test0                                                                                                                                                                                        1.6s
Name:   test
Driver: docker-container

Nodes:
Name:      test0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

At this point your builder is ready to be used. To test the builder we will create a simple Dockerfile and run a multiarch build on it.

#cat Dockerfile
FROM alpine
RUN apk add --no-cache curl netcat-openbsd bash

Because most probably we need to build an image that is different from our current architecture that we are building it on we need to provide the --push option to push the newly created image to the docker repository we want to use. For example hub.docker.com or quay.io but self hosted repo's can also be used but you need to make sure that it will support the storage of a different architectured image than the one it is running on.

#docker buildx build --platform=linux/amd64,linux/arm64 -t <repouser>/debugger:v1 . --push
[+] Building 5.6s (9/9) FINISHED                                                                                                                                                                                                            
 => [internal] load build definition from Dockerfile-test                                                                                                                                                                              0.1s
 => => transferring dockerfile: 36B                                                                                                                                                                                                    0.1s
 => [internal] load .dockerignore                                                                                                                                                                                                      0.0s
 => => transferring context: 2B                                                                                                                                                                                                        0.0s
 => [linux/arm64 internal] load metadata for docker.io/library/alpine:latest                                                                                                                                                           1.4s
 => [linux/amd64 internal] load metadata for docker.io/library/alpine:latest                                                                                                                                                           1.4s
 => [linux/arm64 1/2] FROM docker.io/library/alpine@sha256:a75afd8b57e7f34e4dad8d65e2c7ba2e1975c795ce1ee22fa34f8cf46f96a3be                                                                                                            0.0s
 => => resolve docker.io/library/alpine@sha256:a75afd8b57e7f34e4dad8d65e2c7ba2e1975c795ce1ee22fa34f8cf46f96a3be                                                                                                                        0.0s
 => [linux/amd64 1/2] FROM docker.io/library/alpine@sha256:a75afd8b57e7f34e4dad8d65e2c7ba2e1975c795ce1ee22fa34f8cf46f96a3be                                                                                                            0.0s
 => => resolve docker.io/library/alpine@sha256:a75afd8b57e7f34e4dad8d65e2c7ba2e1975c795ce1ee22fa34f8cf46f96a3be                                                                                                                        0.0s
 => CACHED [linux/arm64 2/2] RUN apk add --no-cache curl netcat-openbsd bash                                                                                                                                                           0.0s
 => CACHED [linux/amd64 2/2] RUN apk add --no-cache curl netcat-openbsd bash                                                                                                                                                           0.0s
 => exporting to image                                                                                                                                                                                                                 4.0s
 => => exporting layers                                                                                                                                                                                                                0.0s
 => => exporting manifest sha256:a3934f3c082fd9526352119c0571d6c0902b7d1a2b7aee2ebf5b6930babc5550                                                                                                                                      0.0s
 => => exporting config sha256:610dc373ad26a047a7532f0b70e5138417f3e2424074c4eb68a4cdec66e8c427                                                                                                                                        0.0s
 => => exporting manifest sha256:1a7da84ff9f98ef1c5b451c54936c4dfd3559a3148305cbbcc4d4146a6b2cc05                                                                                                                                      0.0s
 => => exporting config sha256:dd08d3c07ab36db23b2cb3c83110049746782f6b4741415badbdee7f6619de9d                                                                                                                                        0.0s
 => => exporting manifest list sha256:28e25b51d6235cd185566401d5b9ef9fb9363e3d5d92dcc1dc25c46ad5aa0e10                                                                                                                                 0.0s
 => => pushing layers                                                                                                                                                                                                                  2.6s
 => => pushing manifest for docker.io/<repouser>/debugger:v1

Your docker images are now built and stored into your account in the repository. If you don't provide the docker repo URL by default docker.io will be used.
When you check on the docker repository you will see that the image it is built for multiarch support.

docker image details