## Introduction Les conteneurs promettent des environnements reproductibles, mais les incidents de production surviennent toujours : un conteneur se termine de manière inattendue, une mise à niveau corrompt des données ou une panne d’hôte met hors service des services critiques. Le débogage et la récupération dépendent de la connaissance exacte de l’emplacement des données, des commandes qui révèlent l’état actuel et de la manière de restaurer sans aggraver la situation. Ce guide fournit une procédure pratique pour le débogage, la sauvegarde, la restauration et le retour en arrière de conteneurs Docker. Vous apprendrez à inventorier votre environnement, à inspecter les conteneurs et les volumes, à capturer la configuration, à sauvegarder l’état en toute sécurité et à valider la récupération. Chaque section comprend des commandes concrètes, les sorties attendues et des points de décision. Nous mettons l’accent sur la sécurité opérationnelle : observer avant de modifier, limiter le rayon d’impact, protéger les secrets et vérifier chaque étape. Que vous soyez développeur, ingénieur DevOps ou membre d’une équipe technique de startup, ces pratiques s’appliquent aux hôtes uniques comme aux déploiements multi-nœuds. ## Inventaire des versions et de l’environnement Avant de toucher à un conteneur, sachez ce que vous exécutez. Commencez par un inventaire en lecture seule des versions de Docker, des conteneurs en cours d’exécution, des pilotes de stockage et des projets Compose. Cela crée une base de référence pour le dépannage et la récupération. ### Vérifier Docker et le moteur de conteneurs ```bash docker version ``` La sortie attendue inclut les versions du client et du serveur, le système d’exploitation et l’architecture. Vérifiez que la version de l’API correspond entre le client et le serveur. En cas de divergence, mettez à jour le client ou le démon. ```bash docker system info ``` Recherchez le pilote de stockage (par exemple overlay2), le pilote de journalisation et le nombre de conteneurs/images. Le pilote de stockage affecte la manière dont les instantanés de système de fichiers et les sauvegardes de volumes fonctionnent. ### Lister les conteneurs en cours d’exécution ```bash docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" ``` Cela affiche les noms des conteneurs, leur disponibilité et les mappages de ports. Notez tout conteneur qui redémarre de manière répétée, ce qui indique une boucle de plantage. Pour les projets Compose : ```bash docker compose ps ``` Cela liste les services définis dans `docker-compose.yml` et leur santé. Si un service est manquant, confirmez que vous êtes dans le bon répertoire ou utilisez `-f` pour indiquer le chemin du fichier Compose. ### Inspecter un conteneur ```bash docker inspect ``` L’inspection révèle les montages, les variables d’environnement, les paramètres réseau et les vérifications de santé. Utilisez-la pour vérifier les chemins de données avant la sauvegarde ou la restauration. Par exemple : ```bash docker inspect mon_application --format '{{json .Mounts}}' ``` Cela renvoie un JSON montrant les noms de volumes, les chemins de montage de liaison et les indicateurs de lecture-écriture. Si `"RW": false`, le montage est en lecture seule et peut ne pas nécessiter de sauvegarde. ### Identifier les emplacements de données Les conteneurs peuvent écrire à trois endroits : la couche inscriptible du conteneur, les volumes nommés ou les montages de liaison. La couche inscriptible est éphémère et perdue lorsque le conteneur est supprimé. Les volumes nommés sont gérés par Docker et persistent indépendamment. Les montages de liaison mappent des répertoires hôtes et sont portables si les chemins relatifs sont cohérents. Pour tout service à état (bases de données, files d’attente, téléversements de fichiers), confirmez que les données se trouvent sur un volume ou un montage de liaison. Exemple : ```bash docker inspect mon_postgres --format '{{range .Mounts}}{{println .Name " -> " .Destination}}{{end}}' ``` Sortie attendue : ``` postgres_data -> /var/lib/postgresql/data ``` Si la destination est à l’intérieur du conteneur mais n’a pas de volume ou de montage de liaison correspondant, les données se trouvent dans la couche inscriptible. Déplacez-les immédiatement. ### Documenter l’environnement Créez un fichier d’inventaire simple pour chaque hôte : ```bash docker version > inventaire.txt docker system info >> inventaire.txt docker ps -a >> inventaire.txt ``` Stockez-le hors du conteneur. Lors d’un incident, ce fichier vous aide à identifier la version et la configuration utilisées. ## Démarche de configuration sûre La dérive de configuration provoque de nombreuses défaillances. Avant de modifier un conteneur, capturez sa configuration actuelle et comprenez le plus petit changement qui résout le problème. Séparez toujours l’observation de l’intervention. ### Capturer la configuration actuelle Pour un conteneur en cours d’exécution, exportez sa configuration : ```bash docker inspect > configuration_conteneur.json ``` Pour Compose, archivez l’ensemble du projet : ```bash tar czf sauvegarde_projet_compose.tar.gz docker-compose.yml .env secrets/ ``` Stockez l’archive en lieu sûr. Cela vous permet de restaurer la configuration exacte si un changement casse quelque chose. ### Modifier la configuration en toute sécurité Évitez d’utiliser `docker exec` pour modifier des fichiers à l’intérieur des conteneurs. Les modifications sont perdues lors de la recréation. Utilisez plutôt des variables d’environnement, des fichiers de configuration montés à partir de volumes ou de montages de liaison, ou reconstruisez l’image. Si un conteneur utilise un fichier de configuration monté par liaison, modifiez-le sur l’hôte : ```bash nano ./config/app.conf ``` Puis redémarrez le conteneur : ```bash docker restart ``` Si le service plante à cause d’une mauvaise configuration, revenez au fichier précédent et redémarrez à nouveau. Pour les changements de variables d’environnement, modifiez le fichier Compose ou la commande `docker run` : ```bash docker run -d --name mon_application -e DATABASE_URL=postgres://user:pass@db:5432/madb mon_application:latest ``` Après le changement, vérifiez avec `docker inspect` que la variable est correcte. ### Gérer les secrets Ne codez jamais en dur les secrets dans les fichiers Compose ou les lignes de commande. Utilisez les secrets Docker (Swarm) ou des fichiers d’environnement exclus du contrôle de version : ```bash # Fichier .env (non versionné) DB_PASSWORD=motdepasse_secret ``` Dans Compose : ```yaml services: db: image: postgres:16 environment: POSTGRES_PASSWORD: ${DB_PASSWORD} ``` Exécutez `docker compose config` pour voir la configuration résolue sans exposer les secrets dans les journaux. Masquez les valeurs sensibles lorsque vous partagez des diagnostics. ### Tester les changements de configuration Pour tout changement, appliquez-le d’abord à un conteneur de test. Par exemple, si vous devez modifier un chemin de montage de liaison, lancez un conteneur de test : ```bash docker run -d --name application_test -v ./nouvelles_donnees:/var/lib/app mon_application:latest ``` Vérifiez le fonctionnement, puis appliquez le même changement à la production. Gardez un plan de retour en arrière : le fichier Compose ou la commande précédente. ## Vérification et diagnostics Le diagnostic d’un conteneur défaillant nécessite des vérifications systématiques : journaux, utilisation des ressources, vérifications de santé et connectivité réseau. Passez des symptômes à la cause racine sans modifier l’état prématurément. ### Examiner les journaux ```bash docker logs --tail 100 ``` Ajoutez `-f` pour suivre les journaux en temps réel. Pour des horodatages spécifiques : ```bash docker logs --since 2025-01-01T00:00:00Z ``` Si le conteneur a planté, les journaux peuvent montrer une exception ou un code de sortie. Vérifiez le code de sortie avec : ```bash docker inspect --format '{{.State.ExitCode}}' ``` Le code de sortie 137 signifie souvent une terminaison OOM ; le code 1 peut être une erreur d’application. ### Vérifier l’utilisation des ressources ```bash docker stats --no-stream ``` Cela affiche le CPU, la mémoire et les E/S réseau par conteneur. Si un conteneur dépasse la limite de mémoire, augmentez-la si approprié ou corrigez la fuite. ### Vérifications de santé De nombreuses images définissent des vérifications de santé. Affichez l’état de santé : ```bash docker inspect --format '{{.State.Health.Status}}' ``` S’il est malsain, inspectez la dernière sortie : ```bash docker inspect --format '{{json .State.Health}}' ``` Pour les services sans vérification de santé, testez manuellement. Pour une application web : ```bash docker exec curl -f http://localhost:8080/ || echo "ÉCHEC" ``` ### Diagnostic réseau Vérifiez que le conteneur peut atteindre ses dépendances : ```bash docker exec ping -c 3 db ``` Vérifiez la résolution DNS : ```bash docker exec nslookup db ``` Si le DNS échoue, vérifiez que le conteneur est sur le bon réseau : ```bash docker network inspect ``` ### Vérifications du système de fichiers Inspectez la taille du répertoire de données à l’intérieur du conteneur : ```bash docker exec du -sh /var/lib/app ``` Si le disque est plein, les journaux ou les données peuvent avoir rempli le volume. Nettoyez ou étendez. ## Sauvegarde et restauration des données de conteneurs Les sauvegardes ne valent que par le processus de restauration. Cette section couvre les techniques de sauvegarde pour les volumes de conteneurs, les montages de liaison et la configuration. Testez toujours la restauration sur un environnement séparé avant de vous y fier. ### Sauvegarder un volume nommé Docker n’a pas de commande de sauvegarde de volume intégrée, mais vous pouvez utiliser un conteneur temporaire pour copier les données d’un volume vers une archive tar sur l’hôte. Arrêtez les écritures si possible, ou assurez une faible activité. Pour une base de données, utilisez plutôt son propre outil de sauvegarde (par exemple `pg_dump`), mais pour les volumes généraux : ```bash docker run --rm -v mon_volume:/data -v $(pwd):/sauvegarde alpine tar czf /sauvegarde/sauvegarde_mon_volume.tar.gz -C /data . ``` Cela exécute un conteneur Alpine avec deux montages : le volume nommé dans `/data` et le répertoire hôte actuel dans `/sauvegarde`. La commande `tar` archive le contenu du volume vers l’hôte. ### Sauvegarder un montage de liaison Archivez simplement le répertoire hôte : ```bash tar czf sauvegarde_montage_liaison.tar.gz ./data ``` Pour les grands répertoires, utilisez `rsync` : ```bash rsync -av --delete ./data /emplacement/sauvegarde/ ``` ### Sauvegarder la configuration du conteneur Exportez toujours les configurations de conteneur et les fichiers Compose : ```bash docker inspect > configuration_conteneur.json ``` Pour tous les conteneurs : ```bash docker ps -a --format '{{.Names}}' | while read nom; do docker inspect "$nom" > "${nom}_configuration.json"; done ``` ### Sauvegardes spécifiques aux bases de données Si vous exécutez une base de données dans un conteneur, utilisez son outil de sauvegarde natif pour la cohérence : PostgreSQL : ```bash docker exec -t mon_postgres pg_dump -U postgres madb > sauvegarde_postgres.sql ``` MySQL : ```bash docker exec mon_mysql mysqldump -u root -psecret madb > sauvegarde_mysql.sql ``` Planifiez ces opérations avec cron et stockez hors site. ### Restaurer un volume nommé Restaurez à partir d’une archive tar : ```bash docker run --rm -v mon_volume:/data -v $(pwd):/sauvegarde alpine sh -c "rm -rf /data/* && tar xzf /sauvegarde/sauvegarde_mon_volume.tar.gz -C /data" ``` ### Restaurer une base de données PostgreSQL : ```bash docker exec -i mon_postgres psql -U postgres madb < sauvegarde_postgres.sql ``` ### Valider la restauration Après la restauration, exécutez des tests de fumée de l’application. Pour une application web, vérifiez le point de terminaison de santé : ```bash curl -f http://localhost:8080/health ``` Comparez le nombre de fichiers ou les sommes de contrôle avant et après la sauvegarde si possible. ## Modes de défaillance et récupération Comprendre les modes de défaillance courants vous aide à planifier la récupération. Le tableau 1 liste les défaillances typiques des conteneurs, leurs symptômes et les actions de récupération. | Mode de défaillance | Symptôme | Cause racine | Action de récupération | |---|---|---|---| | Boucle de plantage | Le conteneur redémarre de manière répétée | Erreur d’application, mauvaise configuration, dépendance manquante | Vérifier les journaux, corriger la configuration ou revenir en arrière, redémarrer | | Terminaison OOM | Code de sortie 137 | Limite de mémoire dépassée | Augmenter la limite de mémoire, optimiser l’application, redémarrer | | Disque plein | Les écritures échouent, le conteneur s’arrête | Volume ou disque hôte plein | Nettoyer les anciennes données, étendre le disque, redémarrer | | Réseau injoignable | Impossible de se connecter aux autres services | Mauvais réseau, défaillance DNS | Vérifier l’attachement réseau, la configuration DNS | | Perte de données | Données manquantes après recréation du conteneur | Écriture dans la couche du conteneur, pas dans un volume | Restaurer à partir de la sauvegarde, déplacer vers un volume | | Configuration cassée | Le service plante après un changement de configuration | Faute de frappe ou paramètre invalide | Revenir au fichier de configuration précédent, redémarrer | | Incompatibilité de version | Erreurs d’API après mise à jour de Docker | Discordance client/serveur | Mettre à jour le client ou le démon pour correspondre | ### Stratégies de retour en arrière Pour les images, conservez les étiquettes précédentes : ```bash docker tag mon_application:latest mon_application:prev docker build -t mon_application:latest . # Si la nouvelle image échoue docker tag mon_application:prev mon_application:latest docker service update --force mon_application (Swarm) ou docker-compose up -d ``` Pour la configuration, maintenez des fichiers de configuration versionnés : ```bash cp app.conf app.conf.bak.20250101 ``` Pour revenir en arrière, copiez la sauvegarde et redémarrez. ### Planification de la reprise après sinistre Définissez l’objectif de temps de récupération (RTO) et l’objectif de point de récupération (RPO) pour chaque service. Pour une base de données critique, le RPO peut être de 5 minutes (sauvegardes fréquentes) et le RTO de 30 minutes. Testez la récupération tous les trimestres. Conservez les sauvegardes hors site et chiffrez les données sensibles. Utilisez l’automatisation pour planifier les sauvegardes. ## Liste de contrôle des opérations Utilisez cette liste avant, pendant et après tout changement ou incident de conteneur. Chaque élément inclut un responsable et une fréquence de révision. ### Liste de contrôle avant changement (Responsable : Ingénieur DevOps, révisée avant chaque changement) - [ ] Enregistrer l’état actuel : `docker ps -a`, `docker system info` et les journaux pertinents. - [ ] Confirmer l’emplacement des données : volume ou montage de liaison, pas la couche du conteneur. - [ ] Capturer la configuration : exporter `docker inspect` ou archiver les fichiers Compose. - [ ] Identifier le plan de retour en arrière : étiquette d’image précédente, sauvegarde de fichier de configuration ou instantané de volume. - [ ] Informer les parties prenantes si le changement peut entraîner une interruption. ### Vérification après changement (Responsable : Développeur d’application, révisée après chaque changement) - [ ] Vérifier la santé du conteneur : `docker inspect --format '{{.State.Health.Status}}'` - [ ] Vérifier que le point de terminaison du service renvoie 200 ou la réponse attendue. - [ ] Confirmer l’intégrité des données : comparer le nombre de lignes, de fichiers ou les sommes de contrôle. - [ ] Surveiller les journaux pour les erreurs pendant au moins 10 minutes : `docker logs -f --since 10m ` - [ ] Documenter le changement et son résultat dans le journal des incidents. ### Vérification hebdomadaire des sauvegardes (Responsable : Responsable des opérations, révisée chaque semaine) - [ ] Exécuter la sauvegarde pour tous les volumes et bases de données critiques. - [ ] Vérifier les tailles et horodatages des fichiers de sauvegarde ; s’assurer qu’ils sont récents. - [ ] Tester la restauration d’une sauvegarde vers un environnement de préproduction. - [ ] Vérifier l’intégrité des données restaurées avec des requêtes applicatives. - [ ] Mettre à jour la documentation de sauvegarde si les procédures ont changé. ### Revue de sécurité mensuelle (Responsable : Ingénieur sécurité, révisée chaque mois) - [ ] Analyser les images pour les vulnérabilités : `docker scan ` - [ ] Vérifier les capacités des conteneurs : aucun privilège inutile. - [ ] Examiner la gestion des secrets : s’assurer qu’aucun secret en clair dans les configurations. - [ ] Rotation des informations d’identification utilisées par les conteneurs. - [ ] Vérifier que les politiques réseau isolent les services de manière appropriée. ### Exercice trimestriel de reprise après sinistre (Responsable : Ingénieur fiabilité des sites, révisé chaque trimestre) - [ ] Simuler une panne d’hôte : restaurer les volumes et les bases de données à partir de la sauvegarde vers un nouvel hôte. - [ ] Mesurer le temps de restauration par rapport au RTO. - [ ] Vérifier la fraîcheur des données par rapport au RPO. - [ ] Mettre à jour les procédures opérationnelles en fonction des conclusions de l’exercice. - [ ] Former les membres de l’équipe aux procédures de récupération. ## Pièges courants et comment les éviter Plusieurs erreurs reviennent dans les opérations de conteneurs. Chaque piège ci-dessous inclut pourquoi il se produit et comment l’éviter ou s’en remettre. ### Piège 1 : Stocker des données dans la couche inscriptible du conteneur **Pourquoi cela arrive :** Les développeurs utilisent le conteneur comme une machine virtuelle complète et écrivent dans les chemins par défaut sans configurer de volumes. **Évitement :** Définissez toujours des volumes ou des montages de liaison pour les données à état dans le Dockerfile ou le fichier Compose. **Récupération :** Si les données sont encore accessibles, copiez-les immédiatement : ```bash docker cp mon_conteneur:/var/lib/app ./donnees_recuperees ``` Puis recréez le conteneur avec un volume approprié. ### Piège 2 : Sauvegarder une base de données en direct sans cohérence **Pourquoi cela arrive :** Utiliser `tar` sur les données d’un volume pendant que la base de données écrit peut produire une sauvegarde corrompue. **Évitement :** Utilisez les outils de sauvegarde natifs de la base de données ou arrêtez la base de données avant le `tar`. **Récupération :** Si la sauvegarde est corrompue, restaurez à partir d’une sauvegarde valide précédente ou utilisez les journaux de réplication. ### Piège 3 : Ne pas tester les restaurations **Pourquoi cela arrive :** Les sauvegardes semblent réussies, alors les équipes supposent que la restauration fonctionne. **Évitement :** Planifiez des exercices de restauration réguliers. Automatisez une restauration hebdomadaire vers la préproduction. **Récupération :** Si la restauration échoue pendant un incident, contactez le support du fournisseur ou utilisez une sauvegarde secondaire. ### Piège 4 : Coder en dur les secrets dans les fichiers Compose **Pourquoi cela arrive :** Commodité pendant le développement. **Évitement :** Utilisez des variables d’environnement, des secrets Docker ou un gestionnaire de secrets. **Récupération :** Faites pivoter immédiatement les secrets exposés. Analysez les dépôts de code à la recherche de secrets. ### Piège 5 : Ignorer les limites de ressources **Pourquoi cela arrive :** Les conteneurs fonctionnent bien en test mais peuvent consommer des ressources illimitées en production. **Évitement :** Définissez des limites de CPU et de mémoire dans Compose : ```yaml services: app: image: mon_application deploy: resources: limits: cpus: '0.5' memory: 512M ``` **Récupération :** Si le conteneur est tué par OOM, augmentez la limite de manière appropriée et optimisez l’application. ### Piège 6 : Sauter les vérifications de compatibilité de version **Pourquoi cela arrive :** Le client et le démon Docker sont mis à jour indépendamment. **Évitement :** Gardez le client et le démon sur des versions compatibles ; vérifiez `docker version` avant les changements majeurs. **Récupération :** Rétrogradez ou mettez à niveau si nécessaire ; utilisez la matrice de compatibilité officielle. ## Conclusion Le débogage et la récupération de conteneurs Docker exigent une approche disciplinée : connaissez votre environnement, modifiez avec prudence, vérifiez les résultats et planifiez les défaillances. En suivant les commandes et les listes de contrôle de ce guide, vous réduisez les temps d’arrêt et les pertes de données. Commencez par l’inventaire des versions et de l’environnement pour comprendre votre état actuel. Capturez la configuration avant les modifications, utilisez des diagnostics systématiques et mettez en œuvre des procédures robustes de sauvegarde et de restauration. Répétez régulièrement les exercices de reprise après sinistre. Attribuez des responsables clairs à chaque élément de la liste de contrôle et une fréquence de révision. La liste de contrôle des opérations maintient votre équipe responsable et préparée. Évitez les pièges courants en apprenant d’eux. La conteneurisation offre de l’agilité, mais la rigueur opérationnelle assure la fiabilité. Comme prochaine étape, exécutez l’inventaire de l’environnement sur un hôte, identifiez un conteneur à état sans volume et corrigez-le avant d’avoir besoin d’une sauvegarde.