Pour lâun de mes side projects (une petite webapp), je suis arrivĂ© Ă lâĂ©tape oĂč je devais construire mon image Docker pour embarquer lâapplication. Lâobjectif Ă©tait de la rendre publique pour que nâimporte qui puisse lâutiliser facilement. PlutĂŽt que de la builder uniquement pour lâarchitecture AMD, je me suis dit : « Pourquoi ne pas la rendre aussi compatible ARM ?â, comme ça pas de jaloux, tout le monde pourra lâutiliser, mĂȘme ceux sous Mac M1/M2⊠đ Je me suis donc penchĂ© sur la question du build multi-platform.
Comprendre le build multi-platform
Avant dâaller plus loin, revenons plus en dĂ©tail sur le fonctionnement dâun build multi-platform.
Depuis quelques annĂ©es maintenant, on voit de plus en plus de machines tourner sous ARM que ce soit des Raspberry, des Macs M1/M2/M3/M4 ou des instances AWS Graviton. Mais en parallĂšle, la majoritĂ© des PC et serveurs tournent encore sur de lâAMD64.
Ce sont deux architectures CPU diffĂ©rentes. Je ne vais pas vous faire un cours dâarchitecture processeur, je suis incapable de vous lâexpliquer correctement mdr. Mais retenez juste que ce nâest pas du tout la mĂȘme chose đ€·ââïž.
Sinon, voici la réponse de ChatGPT
ARM : utilise une architecture appelée RISC (Reduced Instruction Set Computing).
â Câest une architecture plus simple, optimisĂ©e pour consommer peu dâĂ©nergie.
â TrĂšs utilisĂ©e dans les smartphones, tablettes, objets connectĂ©s, et maintenant certains PC (comme les Mac M1/M2/M3).AMD : fabrique des processeurs avec lâarchitecture x86 (ou x86-64, plus prĂ©cisĂ©ment).
â Plus complexe, mais puissante, adaptĂ©e aux PC, consoles de jeux, et serveurs.
Et plus les plus curieux je vous laisserai creuser le sujet đ
Cela Ă©tant dit, si vous avez dĂ©jĂ un peu jouĂ© avec Docker, vous voyez peut-ĂȘtre venir le problĂšme. đ
Docker partage le kernel de lâhĂŽte. Du coup, si vous construisez une image pour AMD64, vous ne pouvez pas la faire tourner directement sur une machine ARM. Sauf passer par de lâĂ©mulation mais câest pas ouf.
Câest lĂ que le build multi-platform entre en scĂšne. đ
LâidĂ©e câest de packager plusieurs versions de votre application dans une seule image Docker. En gros, 1 version = 1 arch CPU.
Doooooonc, quand un utilisateur exĂ©cute docker pull depuis sa machine, le client Docker choisit automatiquement la bonne version de lâimage en fonction de son architecture (ARM ou AMD). Et ça, câest franchement top parce-que lâon a plus besoin de maintenir deux images (ou plus), ni de forcer les gens Ă savoir laquelle tĂ©lĂ©charger.
Ok, donc on peut avoir plusieurs images dans une seule image ? Comment câest possible ton truc ? đ€
Une image Docker « classique » contient un seul manifest qui lui mĂȘme contient son fichier de config + son jeu de layers (les instructions du Dockerfile).
Dans le cas dâune image multi-platform, elle contient un index, qui pointe vers plusieurs manifests. Chaque manifest est spĂ©cifique Ă une architecture (ARM64, AMD64, etc.).
Câest cette structure qui permet Ă Docker de faire le tri automatiquement et de tirer la bonne version selon la machine de lâutilisateur.
Si on schématise, ça donne ça :

Si vous voulez comprendre un peu plus le fonctionnement des index je vous laisse avec la doc de docker qui est tipetop.
Et si on automatisait tout ça ?
Je nâaime pas trop trop me rĂ©pĂ©ter alors jâai poussĂ© le truc un peu plus loin. Je me suis demandĂ© si je ne pouvais pas automatiser le build multi platform de ma petite appli avec GitLab CI (vu que j’hĂ©berge dĂ©jĂ le code sur cette plateforme). En fouillant un peu, je suis tombĂ© sur cet article .
Franchement, niquel, ça montre quâil est possible de faire des build multi-plateform avec GitLab CI et lâexemple de lâarticle fonctionne trĂšs bien ! Mais comme souvent avec les exemples âde baseâ tout est codĂ© en dur (les plateformes sur lesquelles on veut build, la registry dans laquelle on veut pushâŠ). Du coup, jâai dĂ©cidĂ© de prendre cet exemple comme point de dĂ©part et de le rendre plus souple et plus rĂ©utilisable. Pour ça, jâai variabilisĂ© au max (plateformes, tag, registry, creds) pour pouvoir intĂ©grer ce job dans nâimporte quel projet. Je ne veux pas avoir Ă toucher au script Ă chaque build ou du moins le moins possible !
Eeeeeeeet, roulement de tambours đ„
ça donne ça :
.build-multi-arch:
image: docker:27.4.1
services:
- docker:dind
before_script:
- test -z $DOCKER_HUB_PAT && echo -e "\e[31m DOCKER_HUB_PAT variable is required to login to DockerHub" && exit 1
- test -z $DOCKER_HUB_USER && echo -e "\e[31m DOCKER_HUB_USER variable is required to login to DockerHub" && exit 1
- echo "$DOCKER_HUB_PAT" | docker login --username "$DOCKER_HUB_USER" --password-stdin
script:
- docker buildx create --use
- docker buildx build --push --platform $IMAGE_PLATFORMS --tag $PUSH_TO_REPO:$IMAGE_TAG .
Il nây a rien de foufou au final. On fait du Docker in Docker pour avoir accĂšs aux commandes docker. Ensuite, jâai ajoutĂ© un before_script pour m’assurer que les variables sont dĂ©finies pour ce connecter sur le DockerHub. Enfin, on build et on push en fonction des plateformes spĂ©cifiĂ©es et de la registry dĂ©finies via les variables.
Jâai tout documentĂ© ici. Pour que ce soit encore plus simple Ă utiliser, jâai créé un template GitLab CI. Le job peut ĂȘtre intĂ©grĂ© dans vos pipelines si vous souhaitez build et publier vos images sur le DockerHub avec plusieurs plateformes. đ
Pour vous la faire giga courte, il suffit dâajouter ce bloc dans vos pipelines :
include:
- https://gitlab.com/Gribhb/am-ci-templates/-/raw/main/jobs/docker/build-multi-arch.yml
build-and-push:
stage: build
extends: .build-multi-arch
variables:
PUSH_TO_REPO: ""
IMAGE_TAG: ""
IMAGE_PLATFORMS: ""
Conclusion
VoilĂ , câĂ©tait un petit article sans prĂ©tention pour vous partager mon exploration autour des builds multi-plateform avec Docker et GitLab CI, suite Ă un besoin perso.
Ăa m’a permis de me challenger un peu pour arriver Ă builder puis publier des images compatibles avec plusieurs plateformes en seulement quelques lignes dans le fichier gitlab-ci. Mission accomplie ! đŻ (je trouve mdr)
Bon, câest sĂ»rement perfectible, mais le rĂ©sultat est lĂ . On peut avoir des dĂ©ploiements dâimages homogĂšnes prĂȘts Ă ĂȘtre utilisĂ©es aussi bien sur Raspberry Pi que sur Mac M1/M2 ou un serveur x86.
Et oui, le plus important ! N’hĂ©sitez pas Ă le forker, Ă l’adapter Ă vos besoins et Ă faire des PR. Je suis preneur de toutes Ă©volutions đ
đ Le code source du template est disponible ici
