Introduction
Le registre Docker est le service central qui stocke et distribue les images de conteneurs. Lorsqu'il tombe en panne, les équipes ne peuvent plus déployer leurs applications. Un simple backend de stockage mal configuré, un certificat TLS expiré ou un disque plein suffit à interrompre toute la chaîne de déploiement. Pour dépanner efficacement un registre, il faut procéder par couches : d'abord inventorier l'environnement, puis effectuer des modifications sans risque, vérifier le comportement avec des commandes concrètes et savoir comment récupérer en cas de problème.
Ce guide s'adresse aux praticiens, que vous soyez un ingénieur plateforme gérant un registre en production ou un développeur réparant un registre local. Chaque étape majeure comprend une commande réelle ou un extrait de configuration avec des explications sur les résultats attendus, pour que vous puissiez suivre facilement. À la fin, vous disposerez d'une liste de contrôle réutilisable, des modes de défaillance courants avec les étapes de récupération, ainsi que des pratiques préventives pour garder votre registre en bonne santé.
Inventaire de la version et de l'environnement
Avant de modifier quoi que ce soit, recueillez des faits concrets sur votre déploiement. Connaître la version du registre, le backend de stockage, la méthode d'authentification, la topologie réseau et les versions des clients évite les suppositions. Tenez un tableau d'inventaire simple et mettez-le à jour dès que l'environnement change. Pour chaque élément ci-dessous, nous fournissons une commande que vous pouvez exécuter maintenant.
Identifier la version du registre
L'image officielle du registre Docker est versionnée par étiquette (tag). Si votre registre s'exécute dans un conteneur, inspectez l'étiquette de l'image :
docker inspect <conteneur-registre> --format '{{.Config.Image}}'
Exemple de sortie attendue :
registry:2.8.3
Si le registre a été installé à partir d'un paquet, interrogez le gestionnaire de paquets :
rpm -q docker-registry # RHEL/CentOS
dpkg -l docker-registry # Debian/Ubuntu
Un registre en bonne santé répond également à l'endpoint de version de l'API :
curl -v http://localhost:5000/v2/
Recherchez une réponse 200 OK avec un corps JSON vide {}. Si vous obtenez un refus de connexion ou un délai d'attente, le service ne tourne pas ou écoute sur un autre port.
Vérifier le backend de stockage
Le backend de stockage est l'endroit où résident les couches d'images et les manifestes. Les backends courants incluent le système de fichiers local, Amazon S3, Azure Blob Storage, Google Cloud Storage et OpenStack Swift. Des informations d'identification mal configurées, des buckets manquants ou des permissions incorrectes sont des causes fréquentes d'erreurs 500 lors des push et pull.
Inspectez le fichier de configuration du registre. Pour un registre conteneurisé, affichez-le directement :
docker exec <conteneur-registre> cat /etc/docker/registry/config.yml
Recherchez la section storage. Voici un exemple de backend système de fichiers :
storage:
filesystem:
rootdirectory: /var/lib/registry
Et un exemple de backend S3 :
storage:
s3:
accesskey: AKIAIOSFODNN7EXAMPLE
secretkey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region: us-east-1
bucket: my-registry-bucket
Notez le type de stockage exact et vérifiez que les informations d'identification sont valides depuis l'hôte du registre. Pour S3, testez avec :
aws s3 ls s3://my-registry-bucket --region us-east-1
Pour le système de fichiers, vérifiez l'espace disque disponible :
df -h /var/lib/registry
Configuration de l'authentification et de TLS
Si votre registre est privé, il utilise probablement une authentification basique, par jeton ou des certificats client TLS. Inspectez les sections auth et http du même fichier de configuration. Exemple avec TLS et authentification basique :
http:
addr: 0.0.0.0:5000
tls:
certificate: /certs/domain.crt
key: /certs/domain.key
auth:
htpasswd:
realm: basic-realm
path: /auth/htpasswd
Pour l'authentification basique, vérifiez que le fichier htpasswd existe et est lisible par le processus du registre. Pour TLS, vérifiez la date d'expiration du certificat :
openssl x509 -enddate -noout -in /certs/domain.crt
Sortie attendue :
notAfter=Mar 14 12:00:00 2026 GMT
Si le certificat est expiré ou si le chemin du fichier htpasswd est incorrect, les clients recevront des erreurs 401 ou des erreurs de vérification de certificat.
Topologie réseau et versions des clients
Cartographiez comment les clients atteignent le registre. Est-ce directement sur le port 5000 ? Derrière un proxy inverse comme nginx ou Traefik ? Derrière un équilibreur de charge ? Chaque couche peut introduire des délais, des réécritures d'en-têtes ou des problèmes de terminaison TLS.
Vérifiez la version du client Docker sur une machine qui effectue des push ou pull :
docker version --format '{{.Client.Version}}'
Exemple :
24.0.5
L'API v2 du registre Docker est rétrocompatible, mais les clients très anciens peuvent ne pas prendre en charge les formats de manifeste plus récents. Si vous suspectez un problème de client, testez avec un client connu comme fonctionnel.
Consignez toutes les découvertes dans un tableau comme celui-ci :
| Composant | Version / Détails | Notes |
|---|---|---|
| Registre | registry:2.8.3 | Conteneurisé |
| Stockage | fichiersystem /var/lib/registry | Volume local |
| TLS | Certificat auto-signé | Valide jusqu'en 2026 |
| Client Docker | 24.0.5 | Sur machine de développement |
| Proxy inverse | nginx 1.24 | Termine TLS |
| OS hôte | Ubuntu 22.04 | Noyau 5.15 |
Chemin de configuration sûr
Modifier la configuration du registre en production sans plan peut prolonger les temps d'arrêt et entraîner des pertes de données. Traitez la configuration comme du code : testez en préproduction, sauvegardez d'abord et appliquez un changement à la fois avec une possibilité de retour en arrière.
Sauvegarder avant de changer
Sauvegardez toujours le fichier de configuration du registre et les données de stockage si possible. Pour un registre conteneurisé, copiez la configuration :
docker cp <conteneur-registre>:/etc/docker/registry/config.yml config.yml.backup
Pour un stockage sur système de fichiers local, créez une archive tar :
tar -czf registry-data-backup-$(date +%Y%m%d).tar.gz /var/lib/registry
Conservez les sauvegardes en dehors de l'hôte du registre, par exemple dans un stockage objet ou un serveur séparé.
Tester en préproduction
Si vous en avez les ressources, lancez un registre jetable localement pour tester les changements avant de les appliquer en production. Démarrez une instance de test sur le port 5001 avec un volume temporaire :
docker run -d -p 5001:5000 --name registry-test \
-v /tmp/registry-test:/var/lib/registry \
registry:2.8.3
Poussez et tirez une image de test pour confirmer le fonctionnement de base. Une fois le test réussi, appliquez le même changement en production.
Changements de configuration progressifs
Lors de l'édition du fichier de configuration principal, modifiez un paramètre à la fois. Par exemple, si vous devez passer du backend de stockage système de fichiers à S3, créez d'abord une configuration de préproduction avec les paramètres S3 et testez-la soigneusement. Utilisez un contrôle de version pour vos fichiers de configuration ; un dépôt Git rend le retour en arrière trivial.
Après l'édition, redémarrez le registre. Avec un simple conteneur Docker, supprimez-le et recréez-le avec le montage mis à jour :
docker stop registry && docker rm registry
docker run -d --name registry -p 5000:5000 \
-v /chemin/vers/config.yml:/etc/docker/registry/config.yml \
-v registry-data:/var/lib/registry \
registry:2.8.3
Avec Docker Compose ou systemd, utilisez la commande de redémarrage habituelle :
docker compose restart registry
# ou
systemctl restart docker-registry
Vérification et diagnostics
Une fois le registre en cours d'exécution, vérifiez sa santé et enquêtez sur les problèmes avec les journaux, les appels API et les tests fonctionnels.
Consulter les journaux du registre
Les journaux sont le premier endroit à regarder pour tout problème. Pour un registre conteneurisé :
docker logs --tail 100 <conteneur-registre>
Pour un service systemd :
journalctl -u docker-registry -n 100 -f
Motifs d'erreur courants dans les journaux :
level=error msg="response completed with error"avec des codes de statut HTTP 500 ou 503 indique une erreur interne.error resolving backendouAccessDeniedpointe vers des problèmes de backend de stockage.TLS handshake errorsuggère des problèmes de certificat.manifest unknownoublob unknownindique des données manquantes ou corrompues.
Exemple d'extrait de journal montrant un problème de permission sur le système de fichiers :
time="2025-02-01T10:00:00Z" level=error msg="error serving image" err="open /var/lib/registry/docker/registry/v2/repositories/...: permission denied"
Vérification de la santé de l'API
Utilisez curl pour vérifier l'API du registre. L'endpoint /v2/ est le contrôle de santé le plus simple :
curl -v http://localhost:5000/v2/
Une réponse saine comprend HTTP/1.1 200 OK et un corps JSON vide {}. Si vous recevez 401 Unauthorized, une authentification est requise ; fournissez les identifiants :
curl -u nom_utilisateur:mot_de_passe -v http://localhost:5000/v2/
Pour un registre utilisant un certificat auto-signé, contournez la vérification avec -k :
curl -k https://localhost:5000/v2/
Si vous recevez 404 Not Found, le registre écoute peut-être sur un autre chemin ou la version de l'API n'est pas prise en charge. Confirmez l'adresse et le port.
Tester le push et le pull d'une image
Le test fonctionnel ultime consiste à pousser et tirer une image réelle. Utilisez une petite image comme alpine :
docker tag alpine:latest localhost:5000/alpine:test
docker push localhost:5000/alpine:test
La sortie attendue montre des barres de progression et un condensé final :
The push refers to repository [localhost:5000/alpine]
...
test: digest: sha256:abcdef... size: 528
Testez ensuite le pull depuis un état propre. Supprimez la copie locale et tirez à nouveau :
docker rmi localhost:5000/alpine:test
docker pull localhost:5000/alpine:test
Si le pull échoue, vérifiez la connectivité réseau, l'authentification et l'accessibilité du stockage des blobs.
Valider l'intégrité du stockage
Pour le stockage sur système de fichiers, vérifiez que les répertoires des dépôts existent et ont les bonnes permissions. Le conteneur du registre s'exécute généralement en tant qu'utilisateur root, mais certains déploiements utilisent un utilisateur non root. Listez la structure des répertoires :
ls -l /var/lib/registry/docker/registry/v2/repositories
La sortie attendue montre des répertoires pour chaque dépôt, par exemple alpine, busybox. Si les permissions sont incorrectes, les journaux du registre afficheront des erreurs permission denied. Corrigez avec :
chown -R registry:registry /var/lib/registry
Pour S3 ou d'autres stockages objet, utilisez leurs outils CLI pour lister les objets et vérifier l'accès. Pour AWS S3 :
aws s3 ls s3://my-registry-bucket/docker/registry/v2/repositories/
Modes de défaillance et récupération
Connaître les schémas de défaillance typiques vous aide à réagir rapidement. Pour chaque mode de défaillance ci-dessous, nous donnons les symptômes, les étapes de diagnostic, les actions de récupération et le retour en arrière si la récupération échoue.
Défaillances du backend de stockage
Symptômes : erreurs 500 lors des push/pull, journaux montrant des erreurs de stockage comme NoSuchBucket, AccessDenied, connection refused ou timeout.
Diagnostic :
- Vérifiez la configuration du stockage dans le fichier de configuration.
- Pour le système de fichiers, vérifiez l'espace disque :
df -h /var/lib/registry. - Pour S3, testez l'accès au bucket :
aws s3 ls s3://bucket-name --region us-east-1. - Consultez les journaux du registre pour des messages d'erreur spécifiques.
Récupération :
- Si le disque est plein, libérez de l'espace en supprimant des images inutiles ou en agrandissant le volume.
- Si les permissions S3 sont erronées, mettez à jour la politique IAM ou les informations d'identification, puis redémarrez le registre.
- Si le bucket n'existe pas, créez-le dans la bonne région et assurez-vous que l'utilisateur du registre a un accès en écriture.
Retour en arrière : restaurez la sauvegarde de configuration précédente et redémarrez le registre. Si des données ont été écrites sur le mauvais backend, vous devrez peut-être re-pousser ou restaurer à partir d'une sauvegarde.
Problèmes d'authentification et de TLS
Symptômes : 401 Unauthorized sur toutes les requêtes, erreurs de vérification de certificat, échec de connexion du client avec échec de la poignée de main TLS.
Diagnostic :
- Vérifiez la section
authdans la configuration ; pour l'authentification basique, vérifiez que le fichier htpasswd existe et est lisible par le processus du registre. - Vérifiez l'expiration du certificat :
openssl x509 -enddate -noout -in domain.crt. - Testez avec
curlet-kpour voir si le problème est spécifique au certificat.
Récupération :
- Renouvelez le certificat TLS et mettez à jour les chemins dans le fichier de configuration, puis redémarrez le registre.
- Si les informations d'identification de l'authentification basique sont incorrectes, régénérez le fichier htpasswd :
htpasswd -Bbn utilisateur mot_de_passe > /auth/htpasswd. - Si vous utilisez une authentification par jeton, vérifiez que l'endpoint du service de jeton est joignable et renvoie des jetons valides.
Retour en arrière : restaurez l'ancien certificat et la configuration d'origine, puis redémarrez.
Problèmes de réseau et de proxy
Symptômes : délais d'attente, refus de connexion, registre inaccessible depuis certains clients mais pas d'autres.
Diagnostic :
- Testez la connectivité du client vers le registre :
nc -zv hôte-registre 5000. - Si derrière un proxy inverse, vérifiez les journaux du proxy pour des erreurs.
- Vérifiez les en-têtes du proxy : le registre attend que
X-Forwarded-Protosoit correctement défini pour la terminaison TLS.
Récupération :
- Corrigez les règles de pare-feu pour autoriser le trafic sur le port du registre.
- Mettez à jour la configuration du proxy pour transmettre les bons en-têtes, par exemple dans nginx :
location /v2/ {
proxy_pass http://registry:5000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
- Redémarrez le service proxy.
Retour en arrière : revenez à la dernière version connue comme fonctionnelle de la configuration du proxy.
Corruption ou perte de données
Symptômes : couches manquantes, erreurs manifest unknown ou blob unknown, erreurs 500 lors du pull.
Diagnostic :
- Inspectez les journaux pour des erreurs de blob ou de manifeste inconnu.
- Exécutez le ramasse-miettes du registre en mode simulation pour voir ce qui serait supprimé :
docker exec <conteneur-registre> bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml
- Pour le stockage sur système de fichiers, vérifiez les fichiers manquants ou de taille nulle dans les répertoires des dépôts.
Récupération :
- Si la corruption est limitée, le ramasse-miettes peut supprimer les blobs non référencés et corriger les incohérences. Exécutez-le sans
--dry-runseulement après une sauvegarde. - Si la corruption est grave, restaurez à partir de la dernière sauvegarde du répertoire ou du volume de stockage.
- Pour le stockage objet, vérifiez si le versionnement des buckets ou des instantanés sont disponibles.
Retour en arrière : restaurez à partir de la sauvegarde puis re-poussez les images ajoutées après la sauvegarde.
Étapes de retour en arrière
Avoir un plan de retour en arrière testé est essentiel. Un retour en arrière manuel simple ressemble à ceci :
# Arrêter le registre
docker stop <conteneur-registre>
# Remplacer la configuration par la sauvegarde
cp config.yml.backup /etc/docker/registry/config.yml
# Si nécessaire, restaurer les données
tar -xzf registry-data-backup.tar.gz -C /
# Redémarrer le registre
docker start <conteneur-registre>
# Vérifier
curl -v http://localhost:5000/v2/
docker push localhost:5000/alpine:test
Si le retour en arrière échoue, ne laissez pas le registre dans un état inconnu. Revenez à la dernière configuration et aux données connues comme bonnes, même si cela implique de perdre temporairement des changements récents. Évitez de faire plusieurs changements à la fois ; cela réduit le risque d'un état irrécupérable.
Pièges courants et comment les éviter
Même les opérateurs expérimentés tombent dans ces pièges. Les reconnaître tôt permet d'économiser des heures de débogage.
1. Modifier la configuration sans sauvegarde
Pourquoi cela arrive : sous la pression, quelqu'un modifie directement config.yml et redémarre le registre, puis découvre que le nouveau paramètre casse tout.
Comment éviter : copiez toujours la configuration vers un fichier de sauvegarde avant de l'éditer. Mieux encore, gardez la configuration sous contrôle de version et ne déployez que des changements testés depuis le dépôt.
Comment récupérer : restaurez immédiatement la sauvegarde, redémarrez et vérifiez.
2. Ignorer l'espace disque jusqu'à ce qu'il soit plein
Pourquoi cela arrive : les registres grossissent silencieusement, et un disque plein provoque des échecs de push et parfois une corruption des données.
Comment éviter : mettez en place une surveillance avec des alertes à 70 % et 85 % d'utilisation du disque. Planifiez un ramasse-miettes régulier avec l'outil intégré du registre.
Comment récupérer : libérez de l'espace en supprimant des images inutilisées ou en agrandissant le volume. Ensuite, exécutez le ramasse-miettes pour nettoyer les blobs orphelins.
3. Ne pas tester la connectivité client après des changements réseau
Pourquoi cela arrive : un changement de pare-feu ou de groupe de sécurité casse la connectivité, mais l'opérateur ne regarde que les journaux côté serveur.
Comment éviter : testez toujours depuis une machine cliente avec nc -zv hôte-registre 5000 et un vrai docker pull avant de clore l'incident.
Comment récupérer : annulez le changement réseau ou ouvrez le port et le protocole nécessaires.
4. Oublier de définir les en-têtes transmis derrière un proxy
Pourquoi cela arrive : la terminaison TLS au niveau du proxy sans définir X-Forwarded-Proto conduit à des URLs incorrectes dans la réponse du registre, cassant les pulls.
Comment éviter : dans la configuration du proxy, définissez toujours X-Forwarded-Proto et X-Forwarded-For. Testez avec curl et inspectez les en-têtes de réponse.
Comment récupérer : ajoutez l'en-tête manquant, redémarrez le proxy et vérifiez avec un pull.
5. Exécuter le ramasse-miettes sans simulation
Pourquoi cela arrive : l'opérateur exécute garbage-collect pour libérer de l'espace, mais il supprime des blobs encore référencés en raison d'une mauvaise configuration, provoquant des échecs de manifeste.
Comment éviter : exécutez toujours avec --dry-run d'abord et inspectez la sortie. Effectuez une sauvegarde complète avant une exécution réelle.
Comment récupérer : restaurez à partir d'une sauvegarde ou re-poussez les images manquantes.
Liste de contrôle des opérations
Utilisez cette liste de contrôle lors des opérations de routine et du dépannage. Pour chaque élément majeur, nous nommons un seul responsable pour éviter toute ambiguïté en cas de problème. Révisez la liste de contrôle mensuellement, ou immédiatement après tout incident.
| Catégorie | Élément à vérifier | Commande / Action | Responsable | Fréquence de révision |
|---|---|---|---|---|
| Pré-dépannage | Confirmer la version du registre et l'emplacement du fichier de configuration | docker inspect <conteneur-registre> --format '{{.Config.Image}}' | Priya Shah, ingénieure plateforme | Mensuelle |
| Pré-dépannage | Vérifier le backend de stockage et l'espace disque | df -h /var/lib/registry | Priya Shah | Hebdomadaire |
| Pré-dépannage | Vérifier la connectivité réseau depuis le client | nc -zv hôte-registre 5000 | Arjun Patel, ingénieur DevOps | Mensuelle |
| Pré-dépannage | Examiner les changements récents dans l'historique Git | git log --oneline -5 config.yml | Priya Shah | Mensuelle |
| Diagnostics | Inspecter les journaux du registre pour des erreurs | docker logs --tail 100 <conteneur-registre> | Arjun Patel | Hebdomadaire |
| Diagnostics | Tester l'endpoint de l'API | curl -v http://localhost:5000/v2/ | Priya Shah | Hebdomadaire |
| Diagnostics | Pousser et tirer une image de test | docker push localhost:5000/alpine:test | Arjun Patel | Mensuelle |
| Diagnostics | Vérifier les permissions du répertoire de stockage | ls -l /var/lib/registry/docker/registry/v2/repositories | Priya Shah | Mensuelle |
| Récupération | Après correction, relancer les vérifications de santé | curl -v http://localhost:5000/v2/ | Priya Shah | Après chaque changement |
| Récupération | Confirmer que le push/pull fonctionne | docker push localhost:5000/alpine:test | Arjun Patel | Après chaque changement |
| Récupération | Surveiller les journaux pour la stabilité | docker logs -f <conteneur-registre> | Arjun Patel | Après chaque changement |
| Préventif | Planifier des sauvegardes régulières | Tâche cron ou outil externe | Priya Shah | Mensuelle |
| Préventif | Surveiller l'utilisation du disque et définir des alertes | Prometheus + Alertmanager | Arjun Patel | Hebdomadaire |
| Préventif | Maintenir le registre et les clients à jour | docker pull registry:2.8.3 | Priya Shah | Trimestrielle |
| Préventif | Tester les changements en préproduction | Instance de registre de préproduction | Arjun Patel | Avant changement en production |
Conclusion
Le dépannage d'un registre Docker est une compétence qui combine une investigation méthodique avec une aisance pratique en ligne de commande. En suivant l'approche par couches de ce guide, de l'inventaire de l'environnement à la récupération en toute sécurité, vous pouvez résoudre la plupart des problèmes sans paniquer. Commencez par un problème étroit et mesurable, par exemple « le push échoue avec une erreur 500 », puis appliquez les étapes de diagnostic dans l'ordre. Utilisez la liste de contrôle pour garder votre registre en bonne santé et partager les connaissances au sein de l'équipe. Documentez vos corrections dans un runbook et entraînez-vous à la récupération dans un laboratoire afin que, lorsqu'un incident réel survient, la réponse soit presque automatique. N'oubliez pas que l'objectif n'est pas seulement de réparer le registre, mais d'empêcher que la même panne ne se reproduise deux fois.