Les images Docker multi-architecture permettent à une seule étiquette de desservir différents types de processeurs, le plus souvent linux/amd64 (Intel/AMD) et linux/arm64 (Apple Silicon, AWS Graviton, Ampere). Avec Docker Buildx, vous pouvez construire les deux architectures en une seule commande, pousser une liste de manifestes et laisser les registres et les clients négocier l'image appropriée au moment du tirage.

Ce guide explique la configuration de Buildx, le choix des cibles de plateforme, la compréhension des limites des tests locaux, l'évitement des pièges de QEMU, la publication des manifestes de registre et l'automatisation des livraisons dans CI.

## Aperçu du workflow

Le flux de bout en bout que vous allez mettre en œuvre :

- Préparer Buildx

- Activer Buildx et créer une instance de builder dédiée.

- En option, enregistrer les émulateurs QEMU pour la compilation croisée quand du matériel natif n'est pas disponible.

- Construire et tester localement

- Construire des images par architecture que vous pouvez charger localement pour des tests de fumée.

- Valider le comportement de base de l'application et les étiquettes d'architecture.

- Construire et pousser en multi-arch

- Construire pour linux/amd64 et linux/arm64 en une seule commande.

- Pousser les images par architecture ainsi qu'une liste de manifestes qui les référence toutes les deux.

- Automatiser dans CI

- Provisionner Buildx dans le job CI.

- S'authentifier auprès du registre.

- Construire, étiqueter et pousser les images multi-arch lors des versions étiquetées.

- Exploiter et dépanner

- Épingler les images de base et les étiquettes pour la reproductibilité.

- Inspecter les manifestes et diagnostiquer les incompatibilités de plateforme.

## Buildx et cibles de plateforme

Docker Buildx étend docker build avec le support multi-plateforme et des fonctionnalités avancées.

- Plateformes : définissez des cibles explicites avec --platform linux/amd64,linux/arm64 . Vous pouvez aussi construire une plateforme à la fois.

- Drivers de builder : le driver docker-container (par défaut pour Buildx) exécute les builds dans un conteneur isolé et gère bien les builds multi-plateforme.

- Manifestes : quand vous poussez un build multi-plateforme, le registre stocke une liste de manifestes qui pointe vers chaque image 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 présentent des angles vifs avec le multi-arch :

- docker buildx build --load ne peut charger qu'une image mono-architecture dans votre magasin d'images Docker 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 disposez de matériel natif.

- Les exécutions émulées sont plus lentes et peuvent masquer ou introduire des problèmes. Utilisez-les uniquement pour des tests de fumée.

Exemples :

# Construire et charger seulement arm64 localement (test de fumée rapide)
docker buildx build \
 --platform linux/arm64 \
 -t myorg/app:arm64-test \
 --load .

# Vérifier l'étiquette d'architecture
docker inspect --format '{{.Os}}/{{.Architecture}}' myorg/app:arm64-test

# Exécuter avec plateforme explicite (peut utiliser l'émulation)
docker run --rm --platform linux/arm64 myorg/app:arm64-test uname -m 

## Mises en garde QEMU

 L'émulation QEMU permet de construire et d'exécuter des images d'architecture étrangère sur votre hôte, mais gardez à l'esprit :

- Elle est plus lente ; prévoyez des minutes à des heures de plus pour les gros builds.

- Certains workloads cassent sous émulation (compilateurs JIT, appels système de bas niveau, boucles de temporisation serrées).

- Les chaînes d'outils qui détectent les caractéristiques CPU à l'exécution peuvent se comporter différemment.

Enregistrer les émulateurs quand nécessaire :

# Enregistrer les émulateurs (nécessite Docker privilégié)
docker run --privileged --rm tonistiigi/binfmt --install all 
 Recommandations :

- Privilégier les builders natifs pour les builds de production. Utiliser l'émulation seulement pour l'expérimentation précoce.

- Maintenir les suites de tests courtes sous QEMU (tests de fumée, pas de packs de régression complets).

- Si un build émulé échoue de manière bizarre, réessayer sur du matériel natif pour confirmer.

## Manifestes de registre et étiquetage

Quand vous poussez un build multi-plateforme, Buildx crée les images par architecture et une liste de manifestes sous votre étiquette.

Inspecter un manifeste :

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 d'étiquetage :

- Utiliser des étiquettes de version immuables (ex. 1.0.0 ) et une étiquette latest mobile pour la commodité.

- Pour le débogage, publier des étiquettes spécifiques à l'architecture en plus de l'étiquette multi-arch :

# Pousser les images spécifiques à l'architecture séparément (facile pour le débogage)
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 simplement. Évitez les surprises d'architecture en utilisant des images de base minimales et largement supportées.

### Exemple minimal multi-étapes (Go)

# syntax=docker/dockerfile:1

# Étape de build
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 garder les différences de libc hors de vos images
ENV CGO_ENABLED=0
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags="-s -w" -o /out/app ./cmd/app

# Étape d'exécution
FROM scratch
COPY --from=build /out/app /app
ENTRYPOINT [

] 
 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 flottes mixtes ou pendant les tests.

version: "3.9"
services:
 web:
 image: myorg/app:1.0.0
 platform: linux/arm64 # forcer arm64 sur hôtes capables
 ports:
 - "8080:8080" 
 Astuce : ne définissez platform dans Compose que lorsque vous avez une raison (par exemple valider le comportement arm64). Sinon laissez le moteur choisir la correspondance native depuis le manifeste.

## Workflow de release CI

Automatisez les builds multi-arch dans CI pour que les releases soient cohérentes.

Exemple avec le CLI Docker dans un job CI générique :

# S'assurer que Docker est disponible et que DinD tourne si nécessaire

# Optionnel : enregistrer les émulateurs pour les builds croisés
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

# Se connecter à votre registre
printf "%s" "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin registry.example.com

# Construire et pousser les images 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 .

# Optionnellement publier des étiquettes de débogage spécifiques à l'architecture
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écuter les builds de release sur des runners natifs quand possible pour éviter les pénalités de performance de QEMU.

- Mettre en cache les couches par architecture. Envisagez --cache-to et --cache-from avec un cache de registre.

## Plan pilote local

Lancez un petit pilote inspectable avant d'étendre à tous les services :

- Choisissez un service conteneurisé simple.

- Rendez son Dockerfile compatible multi-arch (pas de binaires spécifiques à une architecture, image de base minimale).

- Construisez localement pour amd64 et arm64. Chargez une architecture à la fois avec --load et exécutez un test de fumée.

- Poussez vers un registre de test avec étiquettes versionnées et latest .

- Vérifiez le manifeste et la résolution de plateforme :

docker manifest inspect registry.example.com/myorg/app:test | jq '.manifests[].platform' 

- Dans CI, automatisez exactement les mêmes étapes pour les étiquettes correspondant à un motif de release.

 Ce pilote étroit et mesurable est facile à 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 architecture. Retirez avec une étiquette multi-arch ou exécutez avec --platform correspondant à l'image.

- no match for platform in manifest : l'étiquette est mono-arch. Reconstruisez et poussez avec --platform linux/amd64,linux/arm64 .

- qemu: unsupported syscall ou plantages aléatoires sous émulation : réessayez sur matériel natif, réduisez la portée des tests sous QEMU, ou ajustez votre runtime (désactivez les JIT quand possible).

- Builds lents : utilisez des builders natifs, réduisez les couches, et mettez en cache agressivement les dépendances.

- Image de base manquante pour une architecture : choisissez une image de base qui supporte les deux architectures ou compilez depuis les sources dans votre première étape.

## Conclusion

Les images multi-architecture vous permettent de servir les machines arm64 modernes et les hôtes amd64 existants avec une seule étiquette. Buildx offre une façon propre de produire les images par architecture et une liste de manifestes, mais les tests locaux ont des limites et QEMU doit se limiter aux tests de fumée. Commencez par un petit pilote, automatisez le build et le push dans CI, et utilisez un étiquetage clair pour que vos tirages de production résolvent toujours vers l'image correcte.