Intro
Cette version française explique Docker multi-architecture builds with Buildx and platform targets avec le même objectif pratique que l article source : aider le lecteur à comprendre le contexte, les décisions à prendre et les points à vérifier avant de passer à l action.
Les images Docker multi‑architecture permettent d'utiliser un même tag pour plusieurs types de CPU, le plus souvent linux/amd64 (Intel/AMD) et linux/arm64 (Apple Silicon, Graviton, Ampere). Avec Docker Buildx, vous pouvez construire les deux en une seule commande, publier une liste de manifestes (registry manifest) et laisser le registre et le client négocier automatiquement la bonne image au moment du pull.
Ce guide explique comment configurer Docker Buildx, choisir les cibles de plateforme, comprendre les limites des tests locaux, éviter les pièges liés aux QEMU Docker builds, publier des manifests de registre et automatiser une release CI pour des images multi‑architecture Docker images.
Vue d'ensemble du workflow
Voici le flux de bout en bout que vous allez mettre en place :
- Préparer Buildx
- Activer Buildx et un builder.
- Optionnellement enregistrer les émulateurs QEMU pour cross‑builder sans matériel natif.
- Construire et tester en local
- Construire des images par architecture pour des smoke tests.
- Valider le comportement basique de l'app et les labels d'architecture.
- Construire et pousser en multi‑arch
- Construire pour linux/amd64 et linux/arm64.
- Pousser les images par arch plus une liste de manifestes qui référence les deux.
- Automatiser en CI
- Provisionner Buildx dans votre job CI.
- Se connecter au registre.
- Construire, tagger et pousser les images multi‑arch lors des releases versionnées.
- Exploiter et dépanner
- Épingler les images de base et les tags.
- Savoir inspecter les manifests et diagnostiquer les écarts de plateforme.
Buildx et cibles de plateforme
Docker Buildx étend docker build avec la prise en charge multi‑plateforme et des fonctionnalités avancées de Docker BuildKit.
- Plates‑formes : définissez des cibles explicites avec --platform linux/amd64, linux/arm64. Vous pouvez aussi construire une seule plateforme à la fois.
- Drivers du builder : le driver docker-container (par défaut pour Buildx) exécute les builds dans un conteneur isolé et gère très bien le multi‑plateforme.
- Manifests : lors d'un push multi‑plateforme, le registre stocke une manifest list pointant vers les images par architecture. Les clients tirent automatiquement la meilleure correspondance pour leur plateforme.
Commandes courantes :
# Vérifier la disponibilité de Buildx
docker buildx version
# Créer et utiliser un builder dédié
docker buildx create --name multiarch --use
# Initialiser (démarre un conteneur de build si nécessaire)
docker buildx inspect --bootstrap
# Lister les builders
docker buildx ls
Limites des tests locaux
Les tests locaux ont des arêtes vives en multi‑architecture Docker images :
- docker buildx build --load ne peut charger qu'une image mono‑arch dans votre store local. Il ne peut pas charger une liste de manifestes.
- docker run utilise l'architecture de l'hôte par défaut. Vous pouvez demander une autre plateforme avec --platform, mais cela reposera sur l'émulation sauf si vous avez du matériel natif.
- Les exécutions émulées sont plus lentes et peuvent masquer ou introduire des problèmes. Limitez‑vous à des smoke tests.
Exemples :
# Construire et charger seulement arm64 localement (smoke test rapide)
docker buildx build \
--platform linux/arm64 \
-t myorg/app: arm64-test \
--load .
# Vérifier le label d'architecture
docker inspect --format '{{.Os}}/{{.Architecture}}' myorg/app: arm64-test
# Exécuter avec une plateforme explicite (peut utiliser l'émulation)
docker run --rm --platform linux/arm64 myorg/app: arm64-test uname -m
Caveats QEMU
L'émulation QEMU permet de construire et d'exécuter des images d'architecture étrangère sur votre hôte, mais gardez en tête :
- C'est plus lent. Attendez‑vous à des minutes voire des heures supplémentaires pour de gros builds.
- Certains workloads cassent sous émulation (JITs, appels système bas niveau, boucles à timing serré).
- Les toolchains qui détectent les fonctionnalités CPU à l'exécution peuvent se comporter différemment.
Enregistrer les émulateurs si nécessaire :
# Enregistrer les émulateurs (Docker privilégié requis)
docker run --privileged --rm tonistiigi/binfmt --install all
Recommandations :
- Préférez des builders natifs pour les builds de production. Utilisez l'émulation pour l'exploration précoce seulement.
- Raccourcissez les suites de tests sous QEMU (smoke tests, pas de packs de régression complets).
- Si un build émulé échoue de façon étrange, rejouez sur matériel natif pour confirmer.
Manifests de registre et tagging
Quand vous poussez un build multi‑plateforme, Buildx crée des images par architecture et une manifest list sous votre tag.
Inspecter un manifest :
docker buildx build \
--platform linux/amd64, linux/arm64 \
-t registry.example.com/myorg/app:1.0.0 \
-t registry.example.com/myorg/app: latest \
--push .
# Inspecter la liste de manifestes
docker manifest inspect registry.example.com/myorg/app:1.0.0 | jq '.'
Conseils de tagging (Docker image tagging) :
- Utilisez des tags de version immuables (1.0.0) et un latest mouvant pour la commodité.
- Pour le debug, publiez des tags spécifiques à l'arch en plus des tags multi‑arch :
# Pousser séparément des images par arch (pratique pour le debug)
docker buildx build --platform linux/amd64 -t myorg/app:1.0.0-amd64 --push .
docker buildx build --platform linux/arm64 -t myorg/app:1.0.0-arm64 --push .
Exemples de Dockerfile
Commencez simple. Évitez les surprises liées à l'architecture en choisissant des images de base minimales et largement supportées.
Exemple multi‑stage minimal (Go) :
# syntax=docker/dockerfile:1
# Build stage
FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Éviter CGO pour supprimer les différences libc des images
ENV CGO_ENABLED=0
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" -o /out/app ./cmd/app
# Runtime stage
FROM scratch
COPY --from=build /out/app /app
ENTRYPOINT ["/app"]
Notes :
- Utilisez --platform dans votre commande de build ; Buildx injecte automatiquement TARGETOS et TARGETARCH.
- Épinglez les images de base par digest pour la reproductibilité.
Exemple Node.js :
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
FROM --platform=$BUILDPLATFORM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules /app/node_modules
COPY . .
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=build /app/dist /app/dist
ENV NODE_ENV=production
CMD ["node", "dist/index.js"]
Utilisation avec Docker Compose
Compose peut exécuter des services pour une plateforme spécifique. Utile sur des parcs hétérogènes ou en phase de test.
version: "3.9"
services:
web:
image: myorg/app:1.0.0
platform: linux/arm64 # forcer arm64 sur les hôtes compatibles
ports:
- "8080:8080"
Astuce : définissez platform dans Compose uniquement si vous avez une raison (ex. valider le comportement arm64). Sinon, laissez le moteur choisir la variante native à partir du manifest.
Workflow de release en CI
Automatisez les builds multi‑arch dans votre CI pour des releases cohérentes (GitLab CI Docker, etc.).
Exemple avec Docker CLI dans un job CI générique :
# S'assurer que Docker est dispo et que DinD tourne si nécessaire
# Optionnel : enregistrer les émulateurs pour des cross-builds
docker run --privileged --rm tonistiigi/binfmt --install all
# Créer et utiliser un builder Buildx
docker buildx create --name ci-builder --use
docker buildx inspect --bootstrap
# Connexion au registre
printf "%s" "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin registry.example.com
# Build et push multi-arch
APP_IMAGE="registry.example.com/myorg/app"
VERSION="$CI_COMMIT_TAG" # ex. 1.0.0
docker buildx build \
--platform linux/amd64, linux/arm64 \
-t "$APP_IMAGE:$VERSION" \
-t "$APP_IMAGE:latest" \
--push .
# Publier éventuellement des tags de debug par arch
for P in linux/amd64 linux/arm64; do
SFX=$(echo $P | cut -d'/' -f2)
docker buildx build --platform $P -t "$APP_IMAGE:$VERSION-$SFX" --push .
done
Conseils :
- Exécutez les builds de release sur des runners natifs pour éviter les pénalités QEMU.
- Mettez en cache les couches par architecture. Envisagez --cache-to et --cache-from avec un cache de registre.
Plan pilote local
Livrez un petit pilote facilement inspectable avant d'étendre à tous les services :
- Choisir un service conteneurisé simple.
- Rendre son Dockerfile multi‑arch friendly (pas de binaires spécifiques, base minimale).
- Construire localement pour amd64 et arm64. Charger une arch à la fois avec --load et exécuter un smoke test.
- Pousser vers un registre de test avec des tags versionnés et latest.
- Vérifier le manifest et la résolution des plateformes :
docker manifest inspect registry.example.com/myorg/app: test | jq '.manifests[].platform'
- En CI, automatisez exactement les mêmes étapes pour les tags qui correspondent à un schéma de release.
Ce pilote étroit et mesurable est simple à inspecter localement et réduit le risque de déploiement.
Dépannage
- exec format error à l'exécution : vous avez tiré une image pour la mauvaise arch. Re‑pull avec un tag multi‑arch ou exécutez avec un --platform qui correspond à l'image.
- no match for platform in manifest : le tag est mono‑arch. Reconstruisez et poussez avec --platform linux/amd64, linux/arm64.
- qemu: unsupported syscall ou crashes aléatoires sous émulation : rejouez sur matériel natif, réduisez le scope de test sous QEMU, ou ajustez votre runtime (désactivez les JIT si possible).
- Builds lents : utilisez des builders natifs, taillez les couches et mettez agressivement en cache les dépendances.
- Image de base manquante pour une arch : choisissez une base qui supporte les deux architectures ou compilez depuis les sources dans votre premier stage.
Conclusion
Les images multi‑architecture vous permettent de servir les machines arm64 modernes et les hôtes amd64 existants avec un seul tag. Docker Buildx fournit un moyen clair de produire des images par arch et une registry manifest list, mais les tests locaux ont des limites et QEMU est à réserver aux smoke tests. Démarrez avec un petit pilote, automatisez le build et le push en CI, et utilisez un tagging clair pour que vos pulls de production résolvent toujours vers la bonne image. Cette approche réduit les écueils en production et simplifie le troubleshooting dans vos opérations Docker.