
Ce guide vous apprend à construire une seule image qui fonctionne sur plusieurs architectures (amd64, arm64, arm/v7). Avec le même podman pull, l’image appropriée est téléchargée automatiquement.
À la fin, vous saurez :
- Créer un manifest list (index multi-arch)
- Construire avec émulation (simple mais lent)
- Construire avec podman farm (natif et rapide)
- Pousser vers un registry avec un seul tag
Droit au but
Section intitulée « Droit au but »Le besoin : une image pour plusieurs architectures
Section intitulée « Le besoin : une image pour plusieurs architectures »Le problème
Section intitulée « Le problème »Vous avez une image qui fonctionne sur votre machine de développement (probablement amd64). Mais :
- Vos serveurs ARM en production ne peuvent pas l’exécuter
- Vos Raspberry Pi ne peuvent pas l’exécuter
- Vos Mac M1/M2 (arm64) ne peuvent pas l’exécuter nativement
Erreur typique :
podman run myapp:1.0# exec format errorLa solution : manifest list
Section intitulée « La solution : manifest list »Un manifest list (ou “fat manifest”) est un index qui pointe vers plusieurs images, une par architecture :
Quand vous exécutez podman pull myapp:1.0, Podman :
- Télécharge le manifest list
- Identifie l’architecture de votre machine
- Télécharge l’image correspondante
Résultat : le même tag fonctionne partout.
Qu’est-ce qu’un manifest list ?
Section intitulée « Qu’est-ce qu’un manifest list ? »Structure
Section intitulée « Structure »Un manifest list est un fichier JSON stocké dans le registry :
{ "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:abc123...", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:def456...", "platform": { "architecture": "arm64", "os": "linux" } } ]}Architectures courantes
Section intitulée « Architectures courantes »Les architectures les plus fréquentes sont amd64 (serveurs, cloud) et arm64 (Raspberry Pi, Mac M1/M2, AWS Graviton). Les autres sont rares mais utiles pour des cas spécifiques (mainframes IBM, vieux matériel).
| Architecture | Machines | Exemples |
|---|---|---|
linux/amd64 | x86_64, Intel/AMD | Serveurs, cloud, laptops Linux/Windows |
linux/arm64 | ARM 64-bit | Raspberry Pi 4+, Mac M1/M2, AWS Graviton |
linux/arm/v7 | ARM 32-bit | Raspberry Pi 2/3 (mode 32-bit) |
linux/arm/v6 | ARM vieux | Raspberry Pi Zero |
linux/386 | x86 32-bit | Vieux serveurs |
linux/s390x | IBM Z | Mainframes |
linux/ppc64le | IBM Power | Power servers |
Vérifier l’architecture d’une image
Section intitulée « Vérifier l’architecture d’une image »# Voir les architectures disponiblespodman manifest inspect docker.io/library/nginx:alpine
# OU avec skopeo (plus lisible)skopeo inspect --raw docker://docker.io/library/nginx:alpine | jqStratégie 1 : émulation (QEMU)
Section intitulée « Stratégie 1 : émulation (QEMU) »L’émulation permet de construire une image arm64 sur une machine amd64 (et vice versa). C’est la solution la plus simple, mais la plus lente.
Comment ça fonctionne
Section intitulée « Comment ça fonctionne »Configuration
Section intitulée « Configuration »# Installer qemu-user-staticsudo dnf install qemu-user-static
# Vérifierls /usr/bin/qemu-*-static# Installer qemu-user-static et binfmt-supportsudo apt install qemu-user-static binfmt-support
# Enregistrer les handlersdocker run --rm --privileged multiarch/qemu-user-static --reset -p yes# L'émulation est déjà incluse dans Podman Machinepodman machine initpodman machine start
# Vérifierpodman info | grep -A 5 hostConstruire avec —platform
Section intitulée « Construire avec —platform »# Build pour arm64 (émulé sur machine amd64)podman build --platform linux/arm64 -t myapp:arm64 .
# Build pour amd64 (natif sur machine amd64)podman build --platform linux/amd64 -t myapp:amd64 .Performances
Section intitulée « Performances »L’émulation a un coût : QEMU traduit chaque instruction CPU en temps réel. Pour un npm install ou une compilation Go, le ralentissement est significatif. Privilégiez l’émulation pour les tests rapides et podman farm pour les builds de production.
| Architecture cible | Sur machine amd64 | Temps relatif |
|---|---|---|
| linux/amd64 | Natif | 1× |
| linux/arm64 | Émulé | 5-10× |
| linux/arm/v7 | Émulé | 5-10× |
Stratégie 2 : podman farm (builds natifs)
Section intitulée « Stratégie 2 : podman farm (builds natifs) »podman farm distribue les builds sur des machines distantes de chaque architecture. Les builds sont natifs, donc rapides.
Architecture
Section intitulée « Architecture »Prérequis
Section intitulée « Prérequis »Pour chaque machine distante :
- Podman installé
- SSH accessible depuis la machine locale
- Podman socket activé :
# Sur chaque machine distantesystemctl --user enable --now podman.socketConfigurer la farm
Section intitulée « Configurer la farm »-
Ajouter les connexions Podman
Fenêtre de terminal # Machine amd64podman system connection add amd64 ssh://user@amd64-server.local/run/user/1000/podman/podman.sock# Machine arm64podman system connection add arm64 ssh://user@arm64-server.local/run/user/1000/podman/podman.sock# Vérifierpodman system connection list -
Créer la farm
Fenêtre de terminal podman farm create my-farm amd64 arm64# Vérifierpodman farm list -
Tester
Fenêtre de terminal podman farm listRésultat Name Connectionsmy-farm amd64, arm64
Construire avec la farm
Section intitulée « Construire avec la farm »podman farm build \ --farm my-farm \ --platforms linux/amd64,linux/arm64 \ -t registry.example.com/myapp:1.0 \ .Ce qui se passe :
- Le Containerfile est envoyé aux machines distantes
- Chaque machine build pour son architecture (natif)
- Les images sont poussées vers le registry
- Un manifest list est créé avec les deux images
Options de podman farm build
Section intitulée « Options de podman farm build »Les options principales contrôlent la farm utilisée, les architectures cibles, et si le build doit aussi s’exécuter localement.
| Option | Description | Exemple |
|---|---|---|
--farm | Nom de la farm | --farm my-farm |
--platforms | Architectures cibles | linux/amd64,linux/arm64 |
-t, --tag | Tag de l’image | -t registry/app:1.0 |
--local | Build aussi sur la machine locale | --local |
Workflow complet : manifest list
Section intitulée « Workflow complet : manifest list »Si vous avez déjà des images construites (par émulation ou farm), vous pouvez créer manuellement un manifest list.
Commande manifest
Section intitulée « Commande manifest »Les sous-commandes suivent un workflow séquentiel : créer d’abord le manifest vide, puis ajouter les images une par une, puis pousser le tout vers un registry.
| Sous-commande | Action |
|---|---|
manifest create | Créer un nouveau manifest list |
manifest add | Ajouter une image au manifest |
manifest inspect | Voir le contenu du manifest |
manifest push | Pousser le manifest vers un registry |
manifest rm | Supprimer un manifest local |
Workflow manuel
Section intitulée « Workflow manuel »-
Construire les images pour chaque architecture
Fenêtre de terminal # Sur machine amd64podman build --platform linux/amd64 -t myapp:amd64 .# Sur machine arm64 (ou émulé)podman build --platform linux/arm64 -t myapp:arm64 . -
Créer le manifest list
Fenêtre de terminal podman manifest create myapp:1.0 -
Ajouter les images
Fenêtre de terminal # Pour des images locales, préfixer avec containers-storage:podman manifest add myapp:1.0 containers-storage:localhost/myapp:amd64podman manifest add myapp:1.0 containers-storage:localhost/myapp:arm64 -
Vérifier
Fenêtre de terminal podman manifest inspect myapp:1.0Résultat (simplifié) {"manifests": [{"platform": {"architecture": "amd64", "os": "linux"},"digest": "sha256:abc123..."},{"platform": {"architecture": "arm64", "os": "linux"},"digest": "sha256:def456..."}]} -
Pousser vers le registry
Fenêtre de terminal podman manifest push myapp:1.0 registry.example.com/myapp:1.0
Vérifier le résultat
Section intitulée « Vérifier le résultat »Après le push, vérifiez que le manifest list est bien multi-arch :
# Inspecter depuis le registrypodman manifest inspect registry.example.com/myapp:1.0
# Ou avec skopeoskopeo inspect --raw docker://registry.example.com/myapp:1.0 | jq '.manifests[].platform'{"architecture": "amd64", "os": "linux"}{"architecture": "arm64", "os": "linux"}Tester sur différentes architectures
Section intitulée « Tester sur différentes architectures »# Sur machine amd64podman pull registry.example.com/myapp:1.0podman inspect myapp:1.0 --format '{{.Architecture}}'# amd64
# Sur machine arm64podman pull registry.example.com/myapp:1.0podman inspect myapp:1.0 --format '{{.Architecture}}'# arm64Lab : construire une image multi-arch
Section intitulée « Lab : construire une image multi-arch »Objectif : construire une API Go pour amd64 et arm64.
Code de l’application
Section intitulée « Code de l’application »package main
import ( "fmt" "net/http" "runtime")
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from %s/%s\n", runtime.GOOS, runtime.GOARCH) }) http.ListenAndServe(":8080", nil)}# Build stageFROM docker.io/library/golang:1.22-alpine AS builder
WORKDIR /appCOPY main.go .
# Build statique pour l'architecture cibleRUN CGO_ENABLED=0 go build -o /app/server main.go
# Runtime stageFROM scratchCOPY --from=builder /app/server /serverEXPOSE 8080ENTRYPOINT ["/server"]Option A : avec émulation
Section intitulée « Option A : avec émulation »-
Construire les deux architectures
Fenêtre de terminal podman build --platform linux/amd64 -t myapi:amd64 .podman build --platform linux/arm64 -t myapi:arm64 . -
Créer le manifest
Fenêtre de terminal podman manifest create myapi:1.0podman manifest add myapi:1.0 containers-storage:localhost/myapi:amd64podman manifest add myapi:1.0 containers-storage:localhost/myapi:arm64 -
Vérifier
Fenêtre de terminal podman manifest inspect myapi:1.0 -
Pousser
Fenêtre de terminal podman manifest push myapi:1.0 registry.example.com/myapi:1.0
Option B : avec farm
Section intitulée « Option B : avec farm »# Prérequis : farm configurée avec connexions amd64 et arm64
podman farm build \ --farm my-farm \ --platforms linux/amd64,linux/arm64 \ -t registry.example.com/myapi:1.0 \ .Vérification finale
Section intitulée « Vérification finale »# Inspecter le manifest listpodman manifest inspect registry.example.com/myapi:1.0
# Tester sur votre machinepodman run --rm registry.example.com/myapi:1.0# Hello from linux/<votre-arch>
# Forcer une architecture différente (émulé)podman run --rm --platform linux/arm64 registry.example.com/myapi:1.0# Hello from linux/arm64Dépannage
Section intitulée « Dépannage »Erreurs courantes
Section intitulée « Erreurs courantes »La plupart des erreurs viennent de trois sources : l’absence de QEMU pour l’émulation, une image manquante dans le manifest, ou un registry qui ne supporte pas les manifest lists OCI.
| Erreur | Cause | Solution |
|---|---|---|
exec format error | Architecture incompatible | Vérifier --platform ou installer qemu |
no suitable image | Manifest sans cette arch | Ajouter l’image pour cette arch |
failed to push manifest | Registry ne supporte pas OCI index | Utiliser Docker Hub, GitHub, etc. |
| Farm build timeout | Machine distante inaccessible | Vérifier SSH et podman socket |
Commandes de diagnostic
Section intitulée « Commandes de diagnostic »# Architecture de la machine localepodman info --format '{{.Host.Arch}}'
# Vérifier l'émulation disponiblels /proc/sys/fs/binfmt_misc/
# Voir les architectures d'un manifestpodman manifest inspect myapp:1.0 | jq '.manifests[].platform'
# Vérifier les connexions de la farmpodman system connection listpodman farm listL’émulation ne fonctionne pas
Section intitulée « L’émulation ne fonctionne pas »# Vérifier que qemu-user-static est installéls /usr/bin/qemu-*-static
# Réenregistrer les handlers (Linux)docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
# Test rapidepodman run --rm --platform linux/arm64 alpine:3.21 uname -m# aarch64Bonnes pratiques
Section intitulée « Bonnes pratiques »Quand utiliser émulation vs farm
Section intitulée « Quand utiliser émulation vs farm »Le choix dépend de votre contexte : l’émulation est gratuite mais lente, farm est rapide mais nécessite des machines de chaque architecture. Pour la plupart des projets open source, l’émulation suffit.
| Situation | Recommandation |
|---|---|
| Dev local, tests rapides | Émulation |
| CI/CD rapide | Farm |
| Projet open source | Émulation (pas de machines dédiées) |
| Production à grande échelle | Farm |
Optimisations pour le multi-arch
Section intitulée « Optimisations pour le multi-arch »-
Containerfile compatible : éviter les dépendances architecture-spécifiques
# ✅ Bon : dépendances universellesFROM alpine:3.21RUN apk add --no-cache ca-certificates# ❌ Mauvais : binaire compilé pour une seule archCOPY mybinary /app/mybinary -
Multi-stage avec cross-compilation (Go, Rust) :
FROM golang:1.22 AS builderARG TARGETARCH # Variable automatique : arm64 ou amd64RUN GOARCH=${TARGETARCH} go build -o /app -
Tester sur toutes les architectures avant de pousser
Tags et versioning
Section intitulée « Tags et versioning »# Manifest list avec tag sémantiquepodman manifest push myapi:1.0 registry/myapi:1.0.0podman manifest push myapi:1.0 registry/myapi:1.0podman manifest push myapi:1.0 registry/myapi:1podman manifest push myapi:1.0 registry/myapi:latestÀ retenir
Section intitulée « À retenir »- Manifest list = index pointant vers plusieurs images (une par arch)
- Émulation (QEMU) : simple, lente, pas de machine distante
- Farm : builds natifs distribués, rapide, nécessite des machines
- Workflow :
manifest create→add→inspect→push - Vérification :
manifest inspectpour voir les architectures - Test :
--platformpour forcer une architecture (émulée)