## Introduction Les erreurs de configuration du registre Docker peuvent transformer un déploiement de routine en une longue session de débogage. Les opérateurs découvrent souvent une mauvaise configuration seulement après l’échec d’une poussée, un délai d’attente lors d’un tirage, ou une perte de données d’images après un redémarrage. L’objectif de cet article est de vous faire passer d’un problème observé à un résultat vérifié en utilisant des commandes concrètes, les sorties attendues, les signaux d’échec et les étapes de récupération. Ce guide s’adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups qui exploitent ou prévoient d’exploiter un registre Docker auto-hébergé. Il relie les erreurs de configuration, la validation, la restauration et le dépannage aux commandes exactes qui les révèlent. L’accent est mis sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d’action, utiliser des espaces réservés au lieu de secrets, vérifier les résultats et documenter les chemins de récupération. Un registre Docker stocke et distribue des images de conteneurs. Contrairement à Docker Hub, un registre auto-hébergé vous donne le contrôle sur le stockage, les accès et l’emplacement réseau, mais ce contrôle implique des responsabilités. Une mauvaise configuration des backends de stockage, de l’authentification, du TLS ou du garbage collection (ramasse-miettes) peut entraîner des pertes de données ou des temps d’arrêt. Cet article couvre ces risques et vous fournit un flux de travail pour les détecter et les éviter. ## Inventaire des versions et de l’environnement Avant de modifier un fichier de configuration du registre, sachez exactement ce que vous exécutez. Les différences de version du registre Docker (l’image `registry:2`) ou du moteur Docker peuvent modifier l’interprétation des options de configuration. Commencez par des observations en lecture seule : ```bash docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" ``` La sortie attendue montre le nom du conteneur, sa durée de fonctionnement et les ports mappés. Par exemple : ``` NAMES STATUS PORTS registry Up 3 hours 0.0.0.0:5000->5000/tcp ``` Si le conteneur du registre n’est pas listé, il n’est pas en cours d’exécution. Ensuite, vérifiez les journaux : ```bash docker logs registry --tail 100 ``` Recherchez les erreurs de démarrage telles que `level=error msg="configuration error: ..."` ou `level=fatal msg="invalid configuration"`. Ces lignes indiquent souvent le fichier et le numéro de ligne exacts. Pour inspecter les montages, les réseaux, les variables d’environnement ou l’état de santé : ```bash docker inspect registry ``` Pour les projets Compose, utilisez des commandes équivalentes : ```bash docker compose ps docker compose logs -f registry docker compose exec registry sh ``` La dernière commande vous donne un shell dans le conteneur sans reconstruire l’image. ### Où vivent les données : volumes vs montages liés Une erreur courante est de supposer que les données du registre survivent à une recréation du conteneur alors qu’elles résident en réalité dans le système de fichiers du conteneur. Vérifiez la configuration de stockage dans le `config.yml` du registre (généralement monté dans `/etc/docker/registry/config.yml`). Exemple de section de stockage correcte utilisant un volume nommé : ```yaml storage: filesystem: rootdirectory: /var/lib/registry ``` Et dans Compose : ```yaml services: registry: image: registry:2 volumes: - registry_data:/var/lib/registry volumes: registry_data: ``` Ici, `registry_data` est un volume Docker nommé géré par Docker. Il persiste à travers les reconstructions de conteneurs et constitue la configuration recommandée pour la production. Un exemple de montage lié : ```yaml volumes: - ./data:/var/lib/registry ``` Cela mappe un répertoire hôte vers le chemin du conteneur. C’est facile à inspecter mais peut causer des problèmes de permission si le conteneur s’exécute en tant qu’utilisateur non root et que le répertoire hôte n’est pas accessible en écriture. Cela nuit également à la portabilité si le chemin n’existe pas sur une autre machine. ### Test de redémarrage pour la persistance des données Pour vérifier votre configuration de stockage, effectuez un test de redémarrage destructif dans un environnement de staging : ```bash # Arrêter et supprimer le conteneur docker stop registry && docker rm registry # Le recréer avec le même volume # (en supposant que vous utilisiez un fichier Compose ou la commande docker run d'origine) docker run -d --name registry -p 5000:5000 -v registry_data:/var/lib/registry registry:2 # Pousser une image de test, puis vérifier si elle est toujours là après un autre redémarrage docker pull alpine:latest docker tag alpine:latest localhost:5000/test-alpine:1.0 docker push localhost:5000/test-alpine:1.0 # Redémarrer le conteneur docker restart registry # Lister les tags dans le registre à l'aide de l'API curl -s http://localhost:5000/v2/test-alpine/tags/list ``` Sortie attendue : ```json {"name":"test-alpine","tags":["1.0"]} ``` Si la liste des tags est vide ou si la commande curl échoue, les données n’ont pas été persistées correctement. ## Chemin de configuration sûr Modifier la configuration du registre nécessite une approche structurée pour éviter d’interrompre les poussées ou les tirages d’images pour votre équipe. ### Lire la configuration actuelle Tout d’abord, extrayez le fichier de configuration actuel du conteneur en cours d’exécution : ```bash docker cp registry:/etc/docker/registry/config.yml ./config.yml ``` Ou si vous utilisez un montage lié, modifiez le fichier directement. Faites toujours une sauvegarde : ```bash cp config.yml config.yml.bak.$(date +%Y%m%d) ``` ### Comprendre le fichier de configuration Le registre Docker utilise un fichier YAML avec plusieurs sections de premier niveau. Les plus courantes incluent : - `version` : généralement `0.1` - `log` : configuration de journalisation - `storage` : backend de stockage (filesystem, S3, Azure, etc.) - `auth` : méthode d’authentification (par exemple, htpasswd, token) - `http` : paramètres TLS, adresse et secret - `health` : points de terminaison de vérification de santé Une configuration de production minimale avec TLS et authentification : ```yaml version: 0.1 log: level: info fields: service: registry storage: filesystem: rootdirectory: /var/lib/registry http: addr: :443 tls: certificate: /certs/domain.crt key: /certs/domain.key auth: htpasswd: realm: basic-realm path: /auth/htpasswd ``` Cela suppose que vous avez monté les certificats et les fichiers htpasswd. Le registre ne démarre pas si ces chemins sont incorrects. ### Effectuer un seul changement ciblé à la fois Supposons que vous deviez augmenter le niveau de journalisation à `debug` pour le dépannage. Modifiez uniquement le champ `log.level` : Avant : ```yaml log: level: info ``` Après : ```yaml log: level: debug ``` Redémarrez ensuite le registre et surveillez les journaux. Si le changement provoque des erreurs inattendues, revenez immédiatement en arrière. ### Valider la configuration avant de l’appliquer L’image du registre n’inclut pas de commande `validate`, mais vous pouvez vérifier la syntaxe à l’aide d’un analyseur YAML dans un conteneur temporaire : ```bash docker run --rm -v $(pwd)/config.yml:/config.yml -it yamllint yamllint /config.yml ``` Ou utilisez Python si disponible : ```bash docker run --rm -v $(pwd)/config.yml:/config.yml python:3-alpine sh -c "python -c 'import yaml; yaml.safe_load(open(\"/config.yml\"))'" ``` Si la commande se termine par une erreur, corrigez la syntaxe YAML avant de redémarrer. ### Utiliser des variables d’environnement pour les secrets Ne codez jamais en dur les secrets dans le fichier de configuration. Le registre prend en charge la substitution de variables d’environnement dans la configuration. Par exemple, utilisez la variable d’environnement `REGISTRY_STORAGE_S3_ACCESSKEY` pour le stockage S3. Pour l’authentification htpasswd, ne mettez pas le mot de passe en YAML. Montez le fichier htpasswd et définissez les permissions : ```bash docker run -d --name registry \ -p 443:443 \ -v /path/to/certs:/certs \ -v /path/to/auth:/auth \ -e REGISTRY_AUTH=htpasswd \ -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ registry:2 ``` Utilisez un gestionnaire de secrets ou les secrets Docker si disponibles. ## Vérification et diagnostics Après avoir appliqué un changement de configuration, vérifiez que le registre se comporte comme prévu. Cette section couvre les vérifications clés. ### Point de terminaison de santé Le registre v2 fournit un point de terminaison de vérification de santé. Par défaut, il se trouve à `/debug/health` mais vous pouvez configurer un chemin personnalisé. Avec la configuration par défaut, exécutez : ```bash curl -v http://localhost:5000/debug/health ``` Sortie attendue : ```json {} ``` Et un statut HTTP 200. Si le service est défaillant, vous pouvez obtenir un statut non-200 ou une erreur de connexion. ### Vérification de la version de l’API Confirmez la version de l’API du registre : ```bash curl -s http://localhost:5000/v2/ ``` La sortie attendue inclut `{}` avec un statut 200. Si l’authentification est activée, vous obtenez un 401 avec un en-tête `WWW-Authenticate`. ### Tester la poussée et le tirage Créez une petite image de test et poussez-la : ```bash docker pull busybox:latest docker tag busybox:latest localhost:5000/busybox:test docker push localhost:5000/busybox:test ``` Si la poussée réussit, vous voyez la progression du téléversement des couches. Ensuite, tirez l’image sur une autre machine ou après avoir supprimé la copie locale : ```bash docker rmi localhost:5000/busybox:test docker pull localhost:5000/busybox:test ``` Cela valide que le registre accepte non seulement les poussées mais sert également les tirages. ### Vérifier les journaux pour les erreurs Après toute opération, vérifiez les journaux : ```bash docker logs registry --tail 50 ``` Recherchez les lignes avec `level=error` ou `level=warning`. Les erreurs courantes incluent : - `level=error msg="response completed with error" err.code=unknown err.message="blob unknown to registry"` : cela indique un blob manquant, souvent dû à un stockage corrompu ou à une suppression manuelle. - `level=error msg="error serving error json: invalid character ..."` : généralement un problème avec le stockage ou la configuration du registre. ### Surveiller les métriques Si vous avez activé les métriques Prometheus (via `http.debug` ou la section `metrics`), scrapez `http://localhost:5000/metrics`. Vérifiez les compteurs croissants comme `registry_http_requests_total` et les compteurs d’erreurs. ## Modes de défaillance et récupération Même avec une planification minutieuse, des défaillances surviennent. Cette section couvre les modes de défaillance courants et comment les surmonter. ### Défaillance du backend de stockage Si le répertoire racine du système de fichiers devient non accessible en écriture (disque plein, permissions), le registre renvoie des erreurs 500 lors de la poussée. Vous pouvez simuler cela en rendant le répertoire en lecture seule : ```bash chmod 555 /var/lib/registry ``` Essayez ensuite une poussée. Les journaux du registre montrent `level=error msg="error writing blob"`. Pour récupérer : ```bash chmod 755 /var/lib/registry ``` Vérifiez l’espace disque avec `df -h` et nettoyez si nécessaire. ### Mauvaise configuration de l’authentification Si le chemin du fichier htpasswd est incorrect, le registre démarre mais refuse toutes les requêtes authentifiées ou plante. Si le registre ne démarre pas en raison d’un fichier htpasswd manquant, les journaux montrent : ``` level=fatal msg="open /auth/htpasswd: no such file or directory" ``` Corrigez en rectifiant le montage ou en créant le fichier : ```bash docker run --entrypoint htpasswd httpd:2 -Bbn user password > htpasswd ``` Montez-le ensuite correctement. ### Problèmes de certificat TLS Si le certificat est expiré ou ne correspond pas au nom d’hôte, les clients obtiennent `x509: certificate signed by unknown authority` ou `x509: certificate is valid for ... not ...`. Le registre lui-même peut démarrer mais les clients ne parviennent pas à se connecter. Pour récupérer, remplacez les fichiers de certificat et redémarrez le registre. Définissez toujours un rappel pour le renouvellement du certificat. ### Garbage collection qui tourne mal Exécuter le garbage collection (ramasse-miettes) sans arrêter le registre peut entraîner une corruption. La procédure correcte est la suivante : ```bash # Arrêter le registre docker stop registry # Exécuter le garbage collection dans un conteneur temporaire avec le même volume de stockage docker run --rm -v registry_data:/var/lib/registry registry:2 garbage-collect /etc/docker/registry/config.yml # Redémarrer le registre docker start registry ``` Si le registre était en cours d’exécution pendant le GC, vous pouvez voir des erreurs de blob manquant plus tard. Dans ce cas, vous devrez peut-être restaurer à partir d’une sauvegarde ou repousser les images affectées. ### Perte de données due à un mauvais montage de volume Si le répertoire de données n’a pas été monté, après la recréation du conteneur, toutes les images sont perdues. La récupération consiste à identifier les images manquantes et à les repousser depuis les pipelines CI ou les caches locaux. Pour éviter cela, exécutez toujours le test de redémarrage décrit précédemment. ## Erreurs courantes et comment les éviter ### 1. Exécuter sans stockage persistant **Pourquoi cela arrive** : Les développeurs démarrent souvent un registre avec un simple `docker run -d -p 5000:5000 registry:2` pour les tests et oublient d’ajouter un volume. **Comment éviter** : Définissez toujours un volume ou un montage lié. Utilisez Compose pour la reproductibilité. **Récupération** : Si vous avez déjà perdu des données, repoussez les images depuis les pipelines de build. ### 2. Exposer le registre sans TLS **Pourquoi cela arrive** : Pour un usage interne, les équipes sautent le TLS pour économiser des efforts. Mais les clients Docker exigent le TLS à moins que vous ne configuriez des registres non sécurisés. **Comment éviter** : Utilisez un certificat de confiance même en interne. Si vous devez utiliser HTTP, ajoutez explicitement le registre à `insecure-registries` dans la configuration du démon Docker. **Récupération** : Si les clients ne peuvent pas se connecter, ajoutez le registre aux registres non sécurisés ou configurez le TLS. ### 3. Coder en dur les secrets dans les fichiers de configuration **Pourquoi cela arrive** : Les scripts de configuration rapides incluent souvent des mots de passe en YAML. **Comment éviter** : Utilisez la substitution de variables d’environnement ou les secrets Docker. Gardez les fichiers de configuration dans le contrôle de version sans secrets. **Récupération** : Faites tourner les secrets exposés immédiatement. ### 4. Ne pas surveiller l’utilisation du disque **Pourquoi cela arrive** : Les équipes supposent que le stockage sera géré automatiquement. **Comment éviter** : Mettez en place des alertes sur l’espace disque et les métriques du registre. Exécutez périodiquement le garbage collection. **Récupération** : Étendez le disque ou nettoyez les images inutilisées. ### 5. Modifier la configuration sans sauvegarde **Pourquoi cela arrive** : Les changements sont effectués directement sur le serveur sans versionnage. **Comment éviter** : Stockez la configuration dans le contrôle de version. Sauvegardez toujours avant les modifications manuelles. **Récupération** : Restaurez à partir de la sauvegarde ou du contrôle de version. ### 6. Ignorer les journaux du registre **Pourquoi cela arrive** : Les journaux sont considérés comme bruyants ou inaccessibles. **Comment éviter** : Centralisez les journaux et configurez des alertes sur les motifs d’erreur. **Récupération** : Lorsque des problèmes surviennent, commencez par vérifier les journaux ; ils contiennent souvent la solution exacte. ## Liste de contrôle des opérations Utilisez cette liste de contrôle avant et après tout changement de configuration du registre. Chaque élément inclut un rôle responsable et une fréquence de révision. | Élément de la liste | Responsable | Fréquence / Déclencheur | |----------------|-------|---------------------| | Vérifier la version actuelle du registre et la sauvegarde de la configuration | Ingénieur DevOps (par ex., Priya Shah) | Chaque changement | | Confirmer que le volume de stockage est monté et accessible en écriture | Ingénieur DevOps | Chaque changement | | Valider la syntaxe YAML | Ingénieur DevOps | Chaque changement | | Redémarrer le registre et vérifier le point de terminaison de santé | Ingénieur DevOps | Chaque changement | | Pousser et tirer une image de test | Ingénieur QA (par ex., Marcus Lee) | Chaque changement | | Vérifier les journaux pour les erreurs | Ingénieur DevOps | Chaque changement | | Surveiller l’espace disque et les métriques | Administrateur système (par ex., Anna Kowalski) | Hebdomadaire | | Examiner les accès et l’authentification | Agent de sécurité (par ex., Tom Okafor) | Mensuel | | Tester la restauration à partir de la sauvegarde | Ingénieur DevOps | Trimestriel | Toutes les décisions qui affectent la configuration du registre de production doivent être approuvées par le responsable DevOps, et le résultat doit être examiné lors de la réunion mensuelle des opérations. ## Conclusion Les erreurs de configuration du registre Docker sont évitables lorsque vous suivez une approche disciplinée : inventoriez votre environnement, effectuez des changements ciblés avec des sauvegardes, vérifiez avec des commandes concrètes et planifiez la récupération. Le registre est un élément critique de votre infrastructure de conteneurs ; une mauvaise configuration peut bloquer toute la distribution d’images. Commencez par les étapes de vérification à faible risque de ce guide : exécutez le test de redémarrage, vérifiez le point de terminaison de santé et poussez/tirez une image de test. Étendez ensuite vos vérifications au stockage, au TLS et à l’authentification. Un flux de travail fiable rend les défaillances visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de la récupération avant qu’un incident ne force la décision. Gardez cette liste de contrôle à portée de main et révisez-la chaque fois que votre équipe modifie la façon dont les images sont construites et déployées.