Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Registres de conteneurs : comprendre le stockage et la distribution d'images

Par mis à jour le

Améliorer cette page

Vous avez construit une image de conteneur sur votre poste. Comment la déployer sur vos serveurs de production, et comment garantir que toute l'équipe utilise exactement la même version ? La réponse est un registre (registry) : un serveur qui stocke et distribue vos images, comme GitHub pour le code.

Cette leçon explique comment un registre fonctionne sous le capot, du stockage en couches au protocole de pull et de push, puis comment le sécuriser : authentification, références immuables par digest, droits séparés et analyse des images. Elle s'adresse à toute personne qui publie ou consomme des images, et prépare les leçons sur la signature et la chaîne d'approvisionnement.

  • Expliquer ce qu'est un registre et son vocabulaire (repository, tag, digest)
  • Décrire le stockage d'une image : le modèle manifest et couches
  • Suivre ce que font docker pull et docker push sous le capot
  • Distinguer tag mutable et digest immuable, et choisir le bon en production
  • Choisir un type de registre : public, cloud, privé
  • Appliquer les cinq règles de sécurité d'un registre en production

Qu'est-ce qu'une registry d'images de conteneurs ?

Section intitulée « Qu'est-ce qu'une registry d'images de conteneurs ? »

Un registre est le point de passage obligé de toute image entre sa construction et son exécution. Comprendre ce qu'il stocke, et sous quel nom, est la base de tout ce qui suit, notamment de la distinction entre tag et digest.

Un registre (registry) est un serveur de stockage spécialisé qui stocke des images de conteneurs, les distribue à qui en a besoin et les versionne grâce à des étiquettes. C'est l'équivalent, pour les images, de ce qu'est une forge Git pour le code source.

Quatre termes reviennent sans cesse, et les confondre mène à des erreurs de déploiement. Le tableau les distingue, avec un exemple pour chacun ; le digest est celui qui compte le plus en sécurité.

TermeDescriptionExemple
RegistryServeur qui héberge les imagesDocker Hub, Harbor, AWS ECR
RepositoryEspace qui regroupe toutes les versions d'une même imagenginx, mon-app, postgres
TagÉtiquette lisible qui désigne une version1.29.0, stable, latest
DigestEmpreinte SHA256 unique et immuable du contenusha256: suivi de 64 caractères hexadécimaux

Une image est un paquet immobile, stocké dans le registre : c'est le moule. Un conteneur est une application en cours d'exécution, créée à partir de cette image : c'est l'objet moulé qui tourne. Le registre ne contient que des images, jamais de conteneurs.

Sans registre, il faut déployer à la main : copier le code, installer les dépendances, gérer les versions sur chaque serveur. C'est vite ingérable dès qu'on dépasse quelques serveurs, et chaque copie manuelle est une occasion de divergence entre environnements.

Un registre apporte quatre bénéfices, qui deviennent décisifs dès que l'équipe et le nombre de déploiements grandissent. Le dernier, l'intégration à la CI/CD, est celui qui rend les trois autres automatiques.

  1. Reproductibilité : la même image partout, en développement, en préproduction et en production. Fini le « ça marche sur ma machine ».
  2. Déploiements rapides : une construction, N serveurs, et des téléchargements accélérés par la déduplication des couches.
  3. Traçabilité : qui a publié quelle version, quand, sous quel tag.
  4. Intégration CI/CD : le pipeline construit l'image, la pousse sur le registre, et l'orchestrateur (Kubernetes, Nomad) la tire automatiquement.

Vous utilisez peut-être Docker, Podman, containerd ou Kubernetes. Ces outils parlent tous au même registre parce qu'ils respectent des standards ouverts : on peut changer d'outil ou de registre sans réécrire ses scripts, et c'est ce qui évite l'enfermement chez un éditeur.

L'écosystème des conteneurs s'appuie sur les spécifications de l'OCI (Open Container Initiative), qui définit un format d'image et une API de distribution communs, adoptés par tout l'écosystème. Docker, Podman et containerd dialoguent donc avec les registres par les mêmes points d'entrée HTTP /v2/..., et une image construite avec Docker s'exécute dans Kubernetes, qui utilise containerd sous le capot.

L'OCI publie trois spécifications : l'Image Spec (format de l'image : manifests, couches, configuration), la Runtime Spec (comment exécuter un conteneur) et la Distribution Spec (l'API HTTP pour pousser et tirer des images). Le site de l'Open Container Initiative les détaille.

Une image n'est pas un gros fichier unique : c'est un système en couches (layers) organisé par un manifest JSON. Ce découpage explique à la fois la rapidité des téléchargements et la vérification d'intégrité.

Une image se décompose en trois éléments. Le manifest est un document JSON qui énumère les composants de l'image et leur ordre d'empilement. Les couches portent le contenu du système de fichiers, chaque instruction RUN ou COPY d'un Dockerfile en produisant une. Le config blob rassemble les métadonnées d'exécution, dont CMD, ENV et l'utilisateur par défaut.

Structure d'une image : un manifest JSON pointe vers un config blob (CMD, ENV, utilisateur) et vers des couches identifiées chacune par son SHA256.Manifest JSONliste ordonnée des composantsConfig blobCMD, ENV, utilisateurLayer 1sha256:...Layer 2sha256:...Layer 3sha256:...
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

Chaque couche est identifiée par son digest SHA256. Si deux images partagent la même couche, par exemple une même image de base, elle n'est stockée et téléchargée qu'une fois : c'est la déduplication. Elle économise réseau et stockage, et le SHA256 garantit qu'une couche ne peut pas être modifiée sans que son empreinte change.

Quand vous tapez docker pull nginx:1.29.0, le client suit cinq étapes. Les comprendre aide à diagnostiquer un téléchargement lent ou une erreur d'intégrité, et montre où se joue la vérification des couches.

Les cinq étapes d'un docker pull : demander le manifest, recevoir la liste des couches, télécharger les seules couches manquantes, vérifier chaque SHA256, assembler l'image locale.1. Demander le manifest GET /v2/.../manifests/tag2. Recevoir la liste des layers3. Télécharger les layers manquants4. Vérifier chaque SHA2565. Assembler l'image locale
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %
  1. Demande du manifest : le client envoie GET /v2/library/nginx/manifests/1.29.0.
  2. Réception du manifest : le registre répond avec la liste des couches et leurs SHA256.
  3. Téléchargement des couches manquantes : le client ne télécharge que celles qu'il n'a pas déjà localement.
  4. Vérification : chaque couche est contrôlée par son empreinte ; un seul bit modifié fait échouer le téléchargement.
  5. Assemblage : le client empile les couches dans l'ordre, et l'image est prête à s'exécuter.

Le processus inverse publie une image construite localement. Il repose sur la même déduplication : seules les couches absentes du registre voyagent, ce qui rend les publications successives d'une même application légères pour le réseau.

Les quatre étapes d'un docker push : calculer le SHA256 de chaque couche, interroger le registre par HEAD, envoyer les seules couches manquantes, publier le manifest qui associe le tag.1. Calculer le SHA256 de chaque layer2. HEAD sur le registre ce layer existe-t-il ?3. Envoyer les seuls layers manquants4. Publier le manifest PUT /v2/.../manifests/tag
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

Le client calcule le SHA256 de chaque couche, interroge le registre par une requête HEAD pour savoir si elle existe déjà, envoie seulement les couches manquantes, puis publie le manifest par PUT /v2/.../manifests/<tag>. C'est cette dernière étape qui associe le tag au contenu : un tag n'est qu'un pointeur vers un manifest.

Un registre peut être public (tout le monde peut tirer les images) ou privé (authentification requise). Dans tous les cas, la publication doit être authentifiée : qui peut pousser une image peut faire exécuter son code partout où elle est déployée.

Le schéma Bearer Token (standard Docker Registry v2)

Section intitulée « Le schéma Bearer Token (standard Docker Registry v2) »

Sur un registre privé, une requête sans authentification reçoit une réponse 401 Unauthorized avec un en-tête WWW-Authenticate: Bearer realm="..." qui indique le service de jetons. Le client s'y authentifie avec ses identifiants, reçoit un jeton porteur, puis rejoue sa requête avec l'en-tête Authorization: Bearer <jeton>.

Ce jeton est volontairement de courte durée : la spécification de Distribution fixe sa validité à 60 secondes par défaut. Le schéma sépare l'authentification (vérifier l'identité, y compris par LDAP, OAuth ou OIDC) de l'autorisation (vérifier les droits de tirer ou de pousser sur un repository donné).

Le nom complet d'une image suit un format précis, dont plusieurs parties sont implicites. Connaître ces valeurs par défaut évite de tirer une image d'un registre inattendu, un vecteur classique de substitution :

[registre/][namespace/]repository[:tag|@digest]

Le tableau décompose des noms courants. Remarquez que nginx seul signifie en réalité docker.io/library/nginx:latest : un nom court dépend de la configuration du client et d'un tag mutable.

NomRegistreNamespaceRepositoryTag ou digest
nginxdocker.io (implicite)library (implicite)nginxlatest (implicite)
nginx:1.29.0docker.iolibrarynginx1.29.0
myorg/api:2.0.1docker.iomyorgapi2.0.1
harbor.example.com/prod/api:stableharbor.example.comprodapistable
nginx@sha256:<digest>docker.iolibrarynginxDigest SHA256

Une image se référence par un tag ou par un digest, et ce choix décide de la reproductibilité d'un déploiement. C'est la distinction la plus importante de cette leçon pour la sécurité de la chaîne d'approvisionnement.

Un tag est mutable : latest, stable ou même 1.2 peuvent pointer vers des images différentes au fil du temps, et quiconque a le droit de pousser peut le déplacer. Pratique à lire et à partager, il ne garantit pas que docker pull nginx:latest aujourd'hui donne la même image que demain.

Un digest est immuable : sha256:... désigne toujours la même image, bit pour bit. Il garantit l'intégrité et rend un déploiement reproductible ; son seul défaut est d'être peu lisible, avec 64 caractères hexadécimaux. La forme image:tag@sha256:... combine les deux : le tag pour l'humain, le digest pour la machine.

En production, la règle est simple : jamais latest, toujours un tag versionné au minimum, et de préférence un digest. Un redéploiement qui tire un latest déplacé entre-temps peut casser l'application, ou installer une image compromise.

Multi-architecture : une image, plusieurs plateformes

Section intitulée « Multi-architecture : une image, plusieurs plateformes »

Certaines images, comme nginx ou alpine, existent pour plusieurs plateformes : linux/amd64, linux/arm64, parfois windows/amd64. Un même nom d'image sert alors des machines d'architectures différentes sans que l'utilisateur ait à choisir de variante.

Le registre stocke un manifest index (ou manifest list) qui pointe vers un manifest par plateforme. Le client détecte son système et son architecture, puis tire le bon manifest : un développeur sur un Mac ARM64 et un serveur x86_64 utilisent ainsi la même référence. Attention : le digest de l'index et celui d'une plateforme sont différents, ce qui compte quand on épingle.

Image multi-architecture : un manifest index pointe vers un manifest par plateforme (linux/amd64, linux/arm64, windows/amd64), et le client tire celui de sa plateforme.Manifest indexune image, plusieurs plateformesManifestlinux/amd64Manifestlinux/arm64Manifestwindows/amd64Le client tirele manifest de sa plateforme
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

On distingue trois familles de registres : publics, managés dans le cloud et privés hébergés chez soi. Le choix dépend surtout de la souveraineté des données, de l'intégration avec votre cloud et de la charge d'exploitation acceptable.

Pour l'open source, les prototypes et le partage. Les limites de téléchargement de Docker Hub sont à connaître : en CI, elles sont la première cause d'échec inattendu, d'où l'intérêt d'un cache local.

RegistreCaractéristiquesLimites
Docker HubRegistre public historique, gratuit pour les images publiques100 téléchargements par 6 h sans compte, 200 avec un compte Personal
GitHub Container Registry (ghcr.io)Intégré à GitHub ActionsQuotas de stockage selon le plan
Quay.io (Red Hat)Analyse de vulnérabilités, construction automatiquePayant pour le privé

Pour les entreprises déjà sur un cloud : l'intégration avec l'IAM du fournisseur évite de gérer des identifiants séparés, et l'exploitation est déléguée. Les prix sont indicatifs et varient selon la région et l'usage.

RegistrePoints fortsPrix indicatif
AWS ECRIntégration IAM, analyse de vulnérabilitésEnviron 0,10 $ par Go et par mois
Google Artifact RegistryMulti-format (images, Maven, npm), analyseEnviron 0,10 $ par Go et par mois
Azure Container RegistryGéo-réplication, intégration AKSÀ partir d'environ 5 $ par mois (Basic)

Pour la souveraineté des données, la conformité ou les environnements déconnectés. La contrepartie est l'exploitation : haute disponibilité, sauvegardes et mises à jour restent à votre charge.

RegistrePoints fortsComplexité
Distribution (ex-Docker Registry)Open source de référence, simpleBasique, sans interface graphique
HarborInterface, RBAC, analyse Trivy intégrée, réplicationDéploiement Kubernetes recommandé
JFrog ArtifactoryMulti-format, haute disponibilité, LDAP/SAMLPayant, mise en place complexe
Sonatype NexusMulti-format, orienté MavenÉcosystème Java

Quelques repères de choix : Docker Hub pour un prototype, ghcr.io pour une CI/CD sur GitHub, ECR sur AWS, Harbor quand la conformité impose un contrôle total. Les guides Docker Hub, Quay.io et Distribution détaillent chacun.

Cinq règles couvrent l'essentiel de la sécurité d'un registre en production. Elles se renforcent : une image analysée mais référencée par un tag mutable peut être remplacée après l'analyse.

Un secret écrit dans une couche reste lisible par docker history ou en extrayant les couches, même s'il est supprimé dans une couche suivante. Le secret s'injecte au moment de l'exécution, depuis un gestionnaire de secrets, jamais à la construction :

# ❌ MAUVAIS : le secret reste lisible dans une couche de l'image
RUN echo "API_KEY=abc123" >> /app/.env
# Kubernetes : la valeur vient d'un Secret, jamais de l'image
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: api-credentials
key: api-key

Un versionnement strict permet la traçabilité, le retour arrière rapide et la reproductibilité. On publie des tags sémantiques (1.2.3) ou datés avec le commit, jamais latest en production, et le manifeste de déploiement référence le digest :

spec:
containers:
- name: api
image: harbor.example.com/prod/api:1.4.2@sha256:<digest>

3. Utiliser des tokens d'accès, pas de mots de passe

Section intitulée « 3. Utiliser des tokens d'accès, pas de mots de passe »

Les jetons d'accès se révoquent un par un, se renouvellent facilement et portent des droits limités : un jeton en lecture seule pour les déploiements, un jeton d'écriture pour la seule CI. On les passe par l'entrée standard, jamais en argument visible dans l'historique du shell ou la liste des processus :

Fenêtre de terminal
docker login registry.example.org -u robot-ci --password-stdin < "$TOKEN_FILE"

Mieux encore, en CI : une identité de charge de travail par OIDC remplace le jeton longue durée, comme le montre la leçon OIDC : s'authentifier sans secret.

Le moindre privilège s'applique au registre : la plupart des consommateurs n'ont besoin que de tirer. Les pipelines de CI/CD poussent, les serveurs de production tirent seulement, et les développeurs tirent depuis prod/* mais poussent dans dev/*. Avec Harbor, cela se traduit par des rôles par projet :

Projet « prod » : développeurs = Guest (lecture seule)
Projet « dev » : développeurs = Developer (lecture et écriture)

On n'expose pas en production une image porteuse de vulnérabilités connues critiques. Trivy est l'analyseur intégré par défaut à Harbor depuis la version 2.2 ; Clair reste celui de Quay ; Grype est une autre option open source. Le flux recommandé analyse en préproduction, puis promeut :

construire l'image
pousser vers le registre de préproduction
analyser avec Trivy ou Grype
si vulnérabilité critique corrigeable : échec du pipeline
sinon : promotion vers le registre de production, par digest

Les erreurs de registre se ressemblent, mais leur cause se lit dans le code HTTP ou le message. Le tableau associe les plus fréquentes à leur cause probable et à leur correction, sans recourir aux contournements dangereux.

SymptômeCause probableSolution
401 UnauthorizedJeton expiré ou absentSe reconnecter avec docker login
429 Too Many RequestsLimite de téléchargement de Docker HubS'authentifier, ou passer par un cache local
manifest unknownTag inexistant ou faute de frappeLister les tags avec crane ls
Téléchargement lentRegistre éloigné, pas de cacheUtiliser un cache local (proxy Harbor)
Erreur de certificat x509Autorité de certification inconnueAjouter l'autorité au magasin de confiance, plutôt que de désactiver TLS
  1. Un registre stocke et distribue les images de manière centralisée, comme une forge Git pour le code.
  2. Une image, ce sont un manifest et des couches identifiées par leur SHA256, dédupliquées et vérifiées à chaque téléchargement.
  3. Les standards OCI font parler le même protocole /v2/ à Docker, Podman et Kubernetes.
  4. Un tag est mutable, un digest est immuable : en production, on référence par digest et on le rafraîchit régulièrement.
  5. Un jeton de registre est de courte durée et séparé de l'autorisation, qui distingue tirer et pousser.
  6. Cinq règles en production : pas de secret dans les images, versionnement strict, jetons plutôt que mots de passe, droits séparés, analyse avant promotion.

Vérifiez que vous avez retenu l'essentiel de ce guide. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

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

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn