Loading search data...

Construire des images Docker multi-architecture en une seule opération.

Voici une feature de Docker builtx des plus sympathiques. On peut en une seule commande lancer la construction d’images Docker à destination de plusieurs architectures comme les raspberry p1 et même les instance AWS A1.

Pour rappel buildkit est le nouveau moteur de construction d’images intégrant pas mal de nouvelles fonctionnalités.

Et celle-ci vaut le détour. Surtout si vous utilisez plusieurs architectures, linux/amd64, linux/arm64, ou darwin/amd64, … au sein de votre infrastructure.

Mise en place du builder

Le générateur est en fait une image, utilisant les fonctionnalités QEMU, qui tourne au sein d’une instance Docker. Une feature que l’on retrouve sur la version de Docker Desktop d’ailleurs mais caché.

Faisons le test, bien sur dans une machine vagrant. En premier il faut lancer une image permettant d’installer l’outillage nécessaire sur la machine hote.


docker run --privileged --rm tonistiigi/binfmt --install all

Unable to find image 'tonistiigi/binfmt:latest' locally
latest: Pulling from tonistiigi/binfmt
981e1f26977e: Pull complete
6269e8ad230e: Pull complete
Digest: sha256:11128304bc582dc7dbaa35947ff3e52e2610d23cecb410ddfa381a6ce74fa763
Status: Downloaded newer image for tonistiigi/binfmt:latest
installing: arm64 OK
installing: mips64 OK
installing: mips64le OK
installing: arm OK
installing: s390x OK
installing: ppc64le OK
installing: riscv64 OK
{
  "supported": [
    "linux/amd64",
    "linux/arm64",
    "linux/riscv64",
    "linux/ppc64le",
    "linux/s390x",
    "linux/386",
    "linux/arm/v7",
    "linux/arm/v6"
  ],
  "emulators": [
    "qemu-aarch64",
    "qemu-arm",
    "qemu-mips64",
    "qemu-mips64el",
    "qemu-ppc64le",
    "qemu-riscv64",
    "qemu-s390x"
  ]
}

La messe est dite en sortie on pourra avoir des builds à destination de toutes ces archis.

Ensuite viens la création du builder. Pour utiliser une registry perso il faudra utiliser un fichier de config. Plus d’infos ici Pour appeler ce fichier il faudra ajouter --config=/path/to/config.toml

Impact : Je n’utiliserai donc pas l’option --push car pour le moment je n’ai pas reussi à le faire tourner en local. L’option --load n’accepte pas pour le moment de lancer plusieurs build en //.

docker buildx create --driver-opt network=host --driver docker-container --name mybuilder --use
mybuilder
docker buildx inspect --bootstrap
[+] Building 78.2s (1/1) FINISHED
 => [internal] booting buildkit                                                                                                                              78.2s
 => => pulling image moby/buildkit:buildx-stable-1                                                                                                           77.6s
 => => creating container buildx_buildkit_mybuilder0                                                                                                          0.6s
Name:   mybuilder
Driver: docker-container

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

Nous allons utiliser une image plutôt simple :

# syntax=docker/dockerfile:1.3
FROM --platform=$BUILDPLATFORM golang:alpine AS build
 ARG TARGETPLATFORM
 ARG BUILDPLATFORM
 RUN echo "Je cours sur $BUILDPLATFORM, je construis pour $TARGETPLATFORM" > /log
 FROM alpine
 COPY --from=build /log /log

Allez on lance le build (ca va prendre un peu de temps la première fois):

docker buildx build --platform linux/arm64 -t locahost:5000/test-arm64 --load .

[+] Building 0.6s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                          0.1s
 => => transferring dockerfile: 315B                                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                                             0.1s
 => => transferring context: 2B                                                                                                                               0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                              0.3s
 => [internal] load metadata for docker.io/library/golang:alpine                                                                                              0.3s
 => [build 1/2] FROM docker.io/library/golang:alpine@sha256:5519c8752f6b53fc8818dc46e9fda628c99c4e8fd2d2f1df71e1f184e71f47dc                                  0.0s
 => => resolve docker.io/library/golang:alpine@sha256:5519c8752f6b53fc8818dc46e9fda628c99c4e8fd2d2f1df71e1f184e71f47dc                                        0.0s
 => [stage-1 1/2] FROM docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a                                       0.1s
 => => resolve docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a                                               0.0s
 => CACHED [build 2/2] RUN echo "Je cours sur linux/amd64, je construis pour linux/arm64" > /log                                                              0.0s
 => CACHED [stage-1 2/2] COPY --from=build /log /log                                                                                                          0.0s
 => exporting to oci image format                                                                                                                             0.2s
 => => exporting layers                                                                                                                                       0.0s
 => => exporting manifest sha256:17e7bcf7fcb6895660bb46c5c6a5b520eadec6406c07b4b2bf310942d6485e0d                                                             0.0s
 => => exporting config sha256:0a8db5b1ffe94f49fe3be55c3d12b68c96f3fd0deda6bedfa034ecc4d7763ba4                                                               0.0s
 => => sending tarball                                                                                                                                        0.1s
 => importing to docker                                                                                                                                       0.0s

On lance une deuxième plateforme:

docker buildx build --platform linux/amd64 -t locahost:5000/test-amd64 --load .

 => => exporting config sha256:8216a415ef7aa768684334e16ef91fda415f56d15cfd0277306d31b8d4e71d4a                                                               0.0s
 => => sending tarball                                                                                                                                        0.2s
 => importing to docker

Allez on vérifie:

docker images

REPOSITORY                           TAG               IMAGE ID       CREATED          SIZE
locahost:5000/test-amd64             latest            8216a415ef7a   34 seconds ago   5.59MB
locahost:5000/test-arm64             latest            0a8db5b1ffe9   7 minutes ago    5.33MB

Si vous avez une registry, vous pouvez utiliser l’option --push avec plusieurs platefomrs dans la meme ligne de commande. Pour les autres un simple script fera l’affaire.

Pour améliorer les perfs on peut ajouter plusieurs noeuds à votre builder avec l fonction --append.

Franchement ca déchire.

Sources:

Mots clés :

devops tutorials docker

Si vous avez apprécié cet article de blog, vous pouvez m'encourager à produire plus de contenu en m'offrant un café sur Ko-Fi. Vous pouvez aussi passer votre prochaine commande sur amazon, sans que cela ne nous coûte plus cher, via ce lien. Je vous remercie de votre soutien