Vous avez remarqué que docker pull nginx:1.25 ne télécharge pas toujours les mêmes layers ? Deux causes principales :
- Plateforme différente (AMD64 vs ARM64) → layers différentes (images multi-arch)
- Tag mutable → l’image a été rebuild/republishée
Pour comprendre ces comportements, il faut connaître le standard OCI (Open Container Initiative). Ce guide vous explique les concepts clés : tags, digests, manifests, multi-arch et artefacts.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- OCI : le standard ouvert qui définit le format des images et registries
- Tag vs Digest : pourquoi un tag peut changer, pas un digest
- Manifest : le fichier JSON qui décrit une image
- Multi-arch : comment une seule référence sert plusieurs architectures
- Artefacts OCI : stocker des Helm charts, SBOM, signatures dans un registry
Qu’est-ce que l’OCI ?
Section intitulée « Qu’est-ce que l’OCI ? »L’Open Container Initiative (OCI) est une organisation qui définit les standards ouverts pour les conteneurs :
| Spécification | Ce qu’elle définit |
|---|---|
| OCI Image | Format des images (layers, config, manifest) |
| OCI Runtime | Comment exécuter un conteneur (runc) |
| OCI Distribution | API des registries (push, pull, list) |
Pourquoi c’est important ? Grâce à l’OCI, une image buildée avec Docker fonctionne avec Podman, containerd, CRI-O. Un registry comme Harbor, Quay ou GHCR parle le même langage que Docker Hub.
Anatomie d’une image OCI
Section intitulée « Anatomie d’une image OCI »Une image OCI est composée de 3 types d’objets, tous identifiés par leur digest (hash SHA256). C’est un système content-addressable : le contenu détermine l’identifiant, pas l’inverse.
| Objet | Contenu | Identifiant |
|---|---|---|
| Manifest | Référence vers config + layers | sha256:xxx... |
| Config | Métadonnées (env, cmd, user, ports) | sha256:yyy... |
| Layers | Fichiers de chaque couche (tar.gz) | sha256:zzz... |
Le digest d’une image = le hash SHA256 de son manifest. Si le manifest change (même légèrement), le digest change.
Content-addressable vs location-addressable
Section intitulée « Content-addressable vs location-addressable »Contrairement aux URLs classiques (location-addressable), OCI utilise un adressage par contenu :
| Approche | Exemple | Caractéristique |
|---|---|---|
| Location-addressable | https://example.com/image.tar | Même URL, contenu peut changer |
| Content-addressable | sha256:abc123... | Même hash = même contenu garanti |
Avantages du content-addressable :
- Déduplication : layers identiques partagés entre images
- Vérification : intégrité vérifiable par recalcul du hash
- Immutabilité : un digest référence toujours le même contenu
Tag vs Digest : la différence fondamentale
Section intitulée « Tag vs Digest : la différence fondamentale »Le tag : un alias mutable
Section intitulée « Le tag : un alias mutable »Un tag est un nom lisible qui pointe vers un manifest. Le même tag peut pointer vers des manifests différents au fil du temps.
# Aujourd'huinginx:1.25 → sha256:abc123...
# Demain (après un rebuild)nginx:1.25 → sha256:def456... # Différent !C’est comme un signet : il pointe vers une page, mais vous pouvez le déplacer.
Le digest : une empreinte immutable
Section intitulée « Le digest : une empreinte immutable »Un digest est le hash SHA256 du manifest. Il identifie une version exacte de l’image, de manière permanente.
# Toujours la même image, pour toujoursnginx@sha256:6926dd802f40e5e7257fded83e0d8030039642e4e10c4a98a6478e9c6fe06153C’est comme une empreinte digitale : elle ne change jamais pour une personne donnée.
Quand utiliser quoi ?
Section intitulée « Quand utiliser quoi ? »| Contexte | Utiliser | Exemple |
|---|---|---|
| Développement local | Tag | nginx:1.25 |
| CI/CD (publication) | Tag versionné + capturer digest | mon-app:1.2.3 → sha256:abc... |
| Production (deploy) | Digest | mon-app@sha256:abc... |
| Audit / compliance | Digest | Traçabilité exacte |
Dockerfile FROM | Tag ou digest selon criticité | FROM alpine:3.19 ou FROM alpine@sha256:... |
Promotion par digest en CI/CD
Section intitulée « Promotion par digest en CI/CD »Le workflow recommandé pour garantir la traçabilité :
# 1. Build et push avec un tagdocker buildx build --tag ghcr.io/mon-org/mon-app:v1.2.3 --push .
# 2. Capturer le digest depuis le registryDIGEST=$(crane digest ghcr.io/mon-org/mon-app:v1.2.3)echo "Built: ghcr.io/mon-org/mon-app@${DIGEST}" >> release-metadata.txt
# 3. Déployer par digest (immuable)kubectl set image deployment/mon-app \ app=ghcr.io/mon-org/mon-app@${DIGEST}Ce pattern sépare publication (tag pour les humains) et déploiement (digest pour la reproductibilité).
Le manifest : le cœur de l’image
Section intitulée « Le manifest : le cœur de l’image »Le manifest est un fichier JSON qui décrit une image. Il contient :
- Le digest de la config (métadonnées)
- La liste des layers avec leurs digests et tailles
- Le media type (format)
{ "schemaVersion": 2, "mediaType": "application/vnd.oci.image.manifest.v1+json", "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "digest": "sha256:aaa...", "size": 1234 }, "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "digest": "sha256:bbb...", "size": 5678 }, { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "digest": "sha256:ccc...", "size": 9012 } ]}Media types : Docker vs OCI
Section intitulée « Media types : Docker vs OCI »Les registries supportent deux formats de manifests. En pratique, la plupart des outils gèrent les deux de manière transparente.
| Format | Media type manifest | Usage |
|---|---|---|
| Docker v2 | application/vnd.docker.distribution.manifest.v2+json | Legacy, Docker Hub historique |
| OCI | application/vnd.oci.image.manifest.v1+json | Standard actuel, recommandé |
Voir le manifest d’une image :
# Avec cranecrane manifest nginx:1.25 | jq .
# Avec skopeoskopeo inspect --raw docker://nginx:1.25 | jq .Multi-arch : une référence, plusieurs architectures
Section intitulée « Multi-arch : une référence, plusieurs architectures »Comment docker pull nginx télécharge-t-il la bonne version pour votre CPU (AMD64 ou ARM64) ? Grâce au manifest list (ou OCI image index).
Le principe
Section intitulée « Le principe »Un manifest list est un manifest spécial qui contient des références vers plusieurs manifests, un par architecture.
Quand vous faites docker pull nginx:1.25 :
- Docker télécharge le manifest list
- Il identifie votre architecture (ex:
linux/amd64) - Il télécharge le manifest spécifique à votre architecture
- Il télécharge les layers correspondants
Construire des images multi-arch avec Buildx
Section intitulée « Construire des images multi-arch avec Buildx »# Créer un builder multi-plateformedocker buildx create --name multi-arch --driver docker-container --use
# Builder et pusher pour AMD64 + ARM64docker buildx build \ --platform linux/amd64,linux/arm64 \ --tag mon-registry/mon-app:v1.0 \ --push .
# Vérifier les architectures disponiblesdocker manifest inspect mon-registry/mon-app:v1.0Voir les architectures disponibles
Section intitulée « Voir les architectures disponibles »# Avec docker manifestdocker manifest inspect nginx:1.25
# Avec cranecrane manifest nginx:1.25 | jq '.manifests[] | {platform, digest}'
# Résultat{ "platform": { "architecture": "amd64", "os": "linux" }, "digest": "sha256:amd123..."}{ "platform": { "architecture": "arm64", "os": "linux" }, "digest": "sha256:arm123..."}Artefacts OCI : au-delà des images
Section intitulée « Artefacts OCI : au-delà des images »Les registries OCI peuvent stocker d’autres types d’artefacts que des images de conteneurs :
| Artefact | Cas d’usage | Outil |
|---|---|---|
| Helm charts | Packages Kubernetes | helm push |
| SBOM | Liste des composants logiciels | ORAS, Syft |
| Signatures | Attestation d’origine | Cosign, Notation |
| Policies | Règles OPA/Rego | Conftest |
| WASM modules | WebAssembly | ORAS |
OCI 1.1 et la Referrers API
Section intitulée « OCI 1.1 et la Referrers API »Depuis mars 2024, les specs OCI 1.1 permettent d’associer des artefacts à une image via le champ subject. Cela résout un problème majeur : comment savoir quels SBOM, signatures et attestations sont liés à une image ?
Fonctionnement :
- L’artefact (signature, SBOM…) contient un champ
subjectavec le digest de l’image cible - Le registry indexe automatiquement cette relation
- L’API
GET /v2/<name>/referrers/<digest>retourne tous les artefacts liés
# Lister les artefacts liés à une image (avec ORAS)oras discover ghcr.io/mon-org/mon-app:v1.0
# Résultat typiqueghcr.io/mon-org/mon-app@sha256:abc123├── application/vnd.dev.cosign.simplesigning.v1+json (signature)├── application/spdx+json (SBOM)└── application/vnd.in-toto+json (attestation SLSA)ORAS : OCI Registry As Storage
Section intitulée « ORAS : OCI Registry As Storage »ORAS (OCI Registry As Storage) est un outil et une spécification pour pousser/puller n’importe quel fichier vers un registry OCI.
# Pousser un fichier quelconqueoras push ghcr.io/mon-org/configs:v1 config.yaml:application/yaml
# Puller le fichieroras pull ghcr.io/mon-org/configs:v1
# Pousser un SBOM généré par Syft, lié à une image (OCI 1.1)syft nginx:1.25 -o spdx-json > sbom.jsonoras push ghcr.io/mon-org/sboms:nginx-1.25 \ --artifact-type application/spdx+json \ --subject ghcr.io/mon-org/nginx@sha256:abc... \ sbom.json:application/spdx+jsonPourquoi c’est utile ?
- Un seul système pour stocker images, configs, SBOM, signatures
- Même authentification que pour les images
- Même réplication entre registries
- Associer un SBOM ou une signature à une image via son digest
Outils CLI pour manipuler des images OCI
Section intitulée « Outils CLI pour manipuler des images OCI »| Outil | Forces | Installation |
|---|---|---|
| crane | Léger, rapide, API Go réutilisable | go install github.com/google/go-containerregistry/cmd/crane@latest |
| skopeo | Copie entre registries, air-gap | Package système (apt, dnf) |
| regctl | Nettoyage de tags, garbage collection | go install github.com/regclient/regclient/cmd/regctl@latest |
| oras | Artefacts génériques, Referrers API | go install oras.land/oras/cmd/oras@latest |
# Copier une image entre registries (sans Docker daemon)skopeo copy docker://nginx:1.25 docker://mon-registry/nginx:1.25
# Supprimer un tag (attention : irréversible)crane delete mon-registry/mon-app:old-tag
# Explorer les layers d'une imagecrane export nginx:1.25 - | tar -tvf - | head -20Testez vos connaissances
Section intitulée « Testez vos connaissances »Vérifions que vous avez assimilé les concepts OCI essentiels : tags vs digests, manifests, multi-arch et artefacts.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
📋 Récapitulatif de vos réponses
Vérifiez vos réponses avant de soumettre. Cliquez sur une question pour la modifier.
Détail des réponses
À retenir
Section intitulée « À retenir »- OCI = standard ouvert pour images et registries (interopérabilité Docker/Podman/containerd)
- Tag = alias mutable vers un manifest (peut changer) → développement
- Digest = hash SHA256 immutable du manifest → production, audit
- Content-addressable = l’identifiant est le hash du contenu → déduplication, vérification
- Manifest = JSON qui liste config + layers avec leurs digests
- Manifest list = index multi-arch qui pointe vers un manifest par architecture
- OCI 1.1 (mars 2024) = Referrers API pour lier signatures, SBOM, attestations aux images
- ORAS = stocker n’importe quel artefact (SBOM, signatures, configs) dans un registry OCI
- Outils : crane (léger), skopeo (copie), regctl (nettoyage), oras (artefacts)
Pour aller plus loin
Section intitulée « Pour aller plus loin »Prochaine étape
Section intitulée « Prochaine étape »Maintenant que vous comprenez le format OCI, découvrez comment sécuriser votre supply chain d’images avec les SBOM, scans et signatures.