Introduction
Les volumes nommés Docker sont la méthode recommandée pour faire persister les données générées par les conteneurs. Contrairement aux montages de liaison (bind mounts), les volumes nommés sont entièrement gérés par Docker et ne dépendent pas d'une structure de répertoires hôte spécifique. Lorsqu'un conteneur écrit dans un volume nommé, ces données survivent aux redémarrages du conteneur, à sa recréation et même à sa suppression. Pourtant, les volumes échouent encore en production pour des raisons prévisibles : un service écrit dans la couche du conteneur au lieu du point de montage, les permissions sont incorrectes à l'intérieur du conteneur, un volume est attaché au mauvais conteneur, ou des volumes orphelins consomment de l'espace disque jusqu'à ce qu'un déploiement échoue.
Ce guide présente une démarche structurée de dépannage des volumes nommés Docker. Vous apprendrez à faire un inventaire en lecture seule de votre environnement, à inspecter les volumes et les conteneurs pour confirmer où les données résident réellement, à interpréter les messages d'erreur courants, à récupérer des pannes de volume les plus fréquentes, et à terminer avec une liste de vérification opérationnelle qui réduit le risque de répétition d'incident. Chaque section comprend des commandes concrètes et la sortie attendue afin que vous puissiez vérifier chaque étape avant de passer à la suivante.
Inventaire des versions et de l'environnement
Avant de modifier quoi que ce soit, collectez l'état actuel de Docker, du plugin Compose, et des conteneurs ou volumes impliqués. Commencez par les bases :
docker version --format '{{.Server.Version}}'
docker compose version
Sortie attendue :
24.0.7
Docker Compose version v2.23.0
Les versions exactes sont importantes car le comportement des volumes, la prise en charge des pilotes et les options de commande changent entre les versions. Si vous utilisez un pilote de volume tel que local-persist ou un plugin spécifique au cloud, vérifiez que le pilote est installé et actif :
docker plugin ls
Ensuite, listez les conteneurs en cours d'exécution et leur statut :
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
Exemple de sortie :
NAMES STATUS PORTS
web Up 2 hours 0.0.0.0:8080->80/tcp
db Up 20 minutes 5432/tcp
Pour un service en panne, le premier diagnostic en lecture seule est le journal du conteneur. Examinez les 100 dernières lignes et recherchez les erreurs de permission, les erreurs de fichier manquant ou les messages de pilote :
docker logs --tail 100 db
Si les journaux ne révèlent pas le problème, inspectez les points de montage du conteneur et son état de santé :
docker inspect db --format '{{json .Mounts}}' | jq
Sortie attendue (tronquée pour la lisibilité) :
[
{
"Type": "volume",
"Name": "postgres_data",
"Source": "/var/lib/docker/volumes/postgres_data/_data",
"Destination": "/var/lib/postgresql/data",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
Cela vous indique le nom du volume, son chemin hôte réel, la destination dans le conteneur, et s'il est monté en lecture-écriture. Dans un projet Compose, utilisez des commandes équivalentes :
docker compose ps
docker compose logs --tail=100 db
Lorsque des données sont impliquées, confirmez où les fichiers sont stockés avant de recréer un conteneur. Un volume nommé tel que postgres_data:/var/lib/postgresql/data est géré par Docker et réutilisé lors des reconstructions de conteneur. Un montage de liaison tel que ./data:/var/lib/postgresql/data mappe directement un dossier hôte. Les montages de liaison sont pratiques pour le développement, mais ils peuvent échouer sur une autre machine si le chemin absolu diffère ou si l'utilisateur hôte manque de permissions. Les volumes nommés évitent ce type de problème.
Pour vérifier la persistance dans un environnement local, effectuez un test de redémarrage contrôlé. Pour un conteneur nommé db :
docker stop db
docker rm db
docker run -d --name db -v postgres_data:/var/lib/postgresql/data postgres:16
Après le démarrage du nouveau conteneur, vérifiez qu'un fichier précédemment créé existe toujours à l'intérieur du conteneur :
docker exec db ls /var/lib/postgresql/data/
Si le fichier est absent, le conteneur d'origine écrivait probablement à un chemin en dehors du volume monté, comme /var/lib/postgresql au lieu de /var/lib/postgresql/data, ou le volume n'a jamais été monté.
Chemin de configuration sûr
Les modifications de configuration des volumes doivent être petites, versionnées et réversibles. Le chemin le plus sûr est de définir les volumes dans un fichier docker-compose.yml plutôt que de s'appuyer sur des options docker run -v ad hoc, car les fichiers Compose sont plus faciles à auditer et à reproduire.
Commencez avec une configuration Compose minimale qui nomme explicitement le volume :
services:
db:
image: postgres:16
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Exécutez docker compose config pour valider le fichier et afficher la configuration fusionnée finale :
docker compose config
La sortie attendue inclut la déclaration du volume et le montage. Si vous voyez un avertissement concernant un volume non défini, le YAML comporte une coquille ou le volume n'est pas déclaré sous la clé de premier niveau volumes:.
Lorsque vous devez modifier le montage, ne modifiez pas un conteneur en direct. À la place :
- Arrêtez le service :
docker compose stop db
- Sauvegardez les données du volume existant dans une archive tar sur l'hôte :
docker run --rm -v postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/postgres_data_backup.tar.gz -C /data .
Cette commande monte le volume sur /data et le répertoire hôte courant sur /backup, puis crée une archive compressée. Vérifiez que le fichier de sauvegarde existe et n'est pas de taille nulle :
ls -lh postgres_data_backup.tar.gz
Sortie attendue :
-rw-r--r-- 1 user user 52M Feb 20 10:00 postgres_data_backup.tar.gz
- Mettez à jour le fichier Compose, puis recréez le service :
docker compose up -d db
- Confirmez que le service est sain et peut accéder aux données :
docker compose exec db ls /var/lib/postgresql/data
Si les données sont manquantes ou les permissions incorrectes, revenez à la version Compose précédente et restaurez la sauvegarde dans un nouveau volume :
docker volume create postgres_data_restored
docker run --rm -v postgres_data_restored:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/postgres_data_backup.tar.gz"
Puis pointez le service vers postgres_data_restored et redémarrez-le. Cette procédure de restauration n'est possible que si la sauvegarde a été créée avant le changement ; faites de la sauvegarde une étape non négociable pour toute modification de volume.
Un piège courant est de changer le chemin du conteneur sans mettre à jour la configuration de l'application. Par exemple, déplacer le répertoire de données Postgres de /var/lib/postgresql/data vers /var/lib/postgresql/16/main nécessite de définir la variable d'environnement PGDATA en conséquence :
services:
db:
image: postgres:16
environment:
PGDATA: /var/lib/postgresql/16/main
volumes:
- postgres_data:/var/lib/postgresql/16/main
Sans ce chemin explicite, Postgres recherche les données dans son emplacement par défaut et échoue à démarrer, signalant « No data directory! » dans les journaux.
Vérification et diagnostic
Lorsqu'un conteneur signale une erreur liée au stockage, commencez par le volume lui-même. Listez tous les volumes et leurs pilotes :
docker volume ls
Sortie attendue :
DRIVER VOLUME NAME
local postgres_data
local app_uploads
Inspectez un volume spécifique pour voir son point de montage, sa date de création et ses étiquettes :
docker volume inspect postgres_data
Exemple de sortie :
[
{
"CreatedAt": "2025-02-20T10:00:00Z",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "myapp",
"com.docker.compose.volume": "postgres_data"
},
"Mountpoint": "/var/lib/docker/volumes/postgres_data/_data",
"Name": "postgres_data",
"Options": null,
"Scope": "local"
}
]
Le point de montage révèle le répertoire hôte où les données sont stockées. Vous pouvez inspecter le contenu directement, mais soyez prudent : modifier des fichiers pendant que le conteneur fonctionne peut corrompre les données. Pour une vérification en lecture seule, utilisez un conteneur temporaire :
docker run --rm -v postgres_data:/data:ro alpine ls -la /data
La sortie attendue montre les fichiers et leur propriété à l'intérieur du volume. Les erreurs de permission apparaissent souvent ici sous forme de ????? pour l'utilisateur et le groupe, indiquant que l'UID du conteneur ne correspond pas au propriétaire du fichier.
Pour comprendre le décalage de propriété de fichier, obtenez l'UID sous lequel le conteneur s'exécute :
docker inspect --format '{{.Config.User}}' db
Si la sortie est vide, le conteneur s'exécute en tant que root (UID 0). Si les fichiers du volume appartiennent à l'UID 999, un utilisateur non-root du conteneur ne peut pas y écrire. La correction consiste soit à exécuter le conteneur avec un utilisateur correspondant, soit à modifier la propriété des données du volume à l'aide d'un conteneur temporaire :
docker run --rm -v postgres_data:/data alpine chown -R 999:999 /data
Après cette commande, redémarrez le conteneur de base de données et vérifiez les journaux pour un démarrage réussi :
docker restart db
docker logs --tail 50 db
Les lignes de journal attendues incluent :
PostgreSQL init process complete; ready for start up.
...
database system is ready to accept connections
Si le service échoue toujours, activez la journalisation de débogage si disponible. Pour Postgres, définissez log_statement=all et log_min_messages=debug1 dans l'environnement du conteneur ou le fichier de configuration, puis reproduisez l'opération d'écriture et examinez les journaux. Les journaux de débogage montrent souvent le chemin exact du fichier ouvert et l'erreur système, comme Permission denied ou No such file or directory.
Modes de défaillance et récupération
Les volumes nommés échouent de manières limitées. Reconnaître la signature de la défaillance accélère la récupération.
Le volume ne persiste pas les données après la recréation du conteneur
Symptôme : Vous recréez un conteneur avec docker compose up -d et l'application démarre avec un état vide.
Cause : La couche inscriptible du conteneur est utilisée au lieu du volume. Cela se produit lorsque le chemin de montage est incorrect ou que le volume n'est pas attaché au service dans le fichier Compose.
Diagnostic : Pendant que l'ancien conteneur fonctionne encore, inspectez ses montages :
docker inspect myapp --format '{{json .Mounts}}' | jq '.[].Destination'
Si le chemin attendu, comme /var/www/html/uploads, n'est pas listé, le volume est manquant. Recréez ensuite le conteneur et vérifiez à nouveau. S'il n'y a aucun montage, le fichier Compose n'a jamais défini de volume pour ce service.
Récupération : Ajoutez le mappage de volume au fichier Compose puis démarrez le service. Les données écrites dans l'ancienne couche du conteneur sont perdues lorsque le conteneur est supprimé ; si l'ancien conteneur existe toujours, copiez les données avant de le supprimer :
docker cp myapp:/var/www/html/uploads ./uploads-backup
Mettez ensuite à jour le fichier Compose, recréez et copiez les données dans le nouveau volume :
docker compose up -d
docker cp ./uploads-backup/. myapp:/var/www/html/uploads/
Permission refusée à l'intérieur du conteneur
Symptôme : Les journaux de l'application affichent Permission denied lors de l'écriture dans le chemin monté, ou le conteneur se termine avec une erreur.
Cause : La propriété des fichiers hôtes ne correspond pas à l'ID utilisateur (UID) du conteneur. Les volumes nommés héritent de la propriété des données initiales copiées en eux, qui proviennent généralement de l'image. Si le conteneur s'exécute en tant qu'utilisateur non-root, il peut ne pas avoir l'accès en écriture.
Diagnostic : Inspectez l'utilisateur du conteneur et la propriété des fichiers du volume :
docker inspect --format '{{.Config.User}}' app
docker run --rm -v app_uploads:/data:ro alpine ls -ln /data
Comparez l'UID dans la troisième colonne de ls -ln avec l'UID du conteneur. S'ils diffèrent et que l'utilisateur du conteneur n'est pas root, les écritures échoueront.
Récupération : Modifiez la propriété des données du volume pour correspondre à l'utilisateur du conteneur. Par exemple, si le conteneur s'exécute en tant qu'utilisateur www-data avec UID 82, exécutez :
docker run --rm -v app_uploads:/data alpine chown -R 82:82 /data
Alternativement, exécutez le conteneur avec un utilisateur qui correspond à la propriété existante des fichiers, ou utilisez un pilote de volume qui prend en charge la correspondance automatique des permissions (par exemple, :z ou :Z sur les systèmes SELinux).
Volumes orphelins consommant de l'espace disque
Symptôme : L'hôte manque d'espace disque et docker system df montre une utilisation élevée des volumes.
Cause : Les volumes qui ne sont plus utilisés par aucun conteneur ne sont pas automatiquement supprimés. Avec le temps, ils s'accumulent.
Diagnostic : Listez les volumes et leur utilisation :
docker system df -v
Cherchez les volumes sans nom de conteneur associé dans la colonne « Links ». Listez également les volumes non référencés par aucun conteneur :
docker volume ls -f dangling=true
Récupération : Avant de supprimer un volume, confirmez qu'il est vraiment orphelin. Inspectez ses métadonnées et, si possible, créez un conteneur temporaire pour lister son contenu :
docker run --rm -v <volume_name>:/data alpine ls -la /data
Si les données ne sont pas nécessaires, supprimez le volume :
docker volume rm <volume_name>
Pour éviter la récurrence, planifiez un nettoyage périodique avec une alerte de surveillance. Par exemple, une tâche cron qui s'exécute chaque semaine et supprime tous les volumes en suspens non utilisés au cours des 30 derniers jours (attention : c'est une commande destructive ; ayez toujours des sauvegardes) :
docker volume prune --filter "label!=keep"
Sauvegarde et restauration de volume
Symptôme : Vous devez migrer un volume vers un autre hôte ou restaurer après une corruption de données.
Cause : Les volumes sont locaux à l'hôte par défaut ; ils ne sont pas portables sauf s'ils sont sauvegardés.
Procédure : Utilisez un conteneur temporaire pour créer une archive compressée du contenu du volume. Copiez ensuite l'archive vers le nouvel hôte et extrayez-la dans un nouveau volume.
Sur l'hôte source :
docker run --rm -v my_volume:/data -v $(pwd):/backup alpine tar czf /backup/my_volume_backup.tar.gz -C /data .
Transférez my_volume_backup.tar.gz vers l'hôte cible avec scp ou un seau de stockage cloud. Sur l'hôte cible :
docker volume create my_volume_new
docker run --rm -v my_volume_new:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/my_volume_backup.tar.gz"
Puis pointez le conteneur vers my_volume_new. Testez la restauration en démarrant un conteneur en lecture seule et en vérifiant l'intégrité des fichiers.
Liste de vérification opérationnelle
Adoptez cette liste de vérification avant tout changement lié aux volumes dans un environnement de production. Attribuez un seul responsable, par exemple « Priya Shah, Responsable Ingénierie », qui est chargé de vérifier chaque élément. Révisez la liste de vérification mensuellement pour l'adapter aux nouveaux modèles de défaillance.
Liste de vérification pré-changement
- [ ] Responsable : Priya Shah, Responsable Ingénierie. Date : 2025-02-20.
- [ ] Exécutez
docker versionetdocker compose version; enregistrez la sortie. - [ ] Exécutez
docker ps --format "table {{.Names}}\t{{.Status}}"et identifiez le conteneur cible. - [ ] Inspectez les montages du conteneur :
docker inspect <container> --format '{{json .Mounts}}'et confirmez le nom du volume et le point de montage. - [ ] Vérifiez l'utilisation du volume :
docker system df -v | grep <volume_name>pour voir la consommation de disque. - [ ] Créez une sauvegarde du volume avec un horodatage :
docker run --rm -v <volume>:/data -v $(pwd):/backup alpine tar czf /backup/<volume>_backup_$(date +%Y%m%d).tar.gz -C /data . - [ ] Vérifiez la taille de la sauvegarde et listez le contenu :
tar tzf <backup_file> | head. - [ ] Notez le plan de retour en arrière : la version précédente du fichier Compose et la commande pour restaurer la sauvegarde dans un nouveau volume.
Pendant le changement
- [ ] Arrêtez le service avec
docker compose stop <service>. - [ ] Effectuez la modification de configuration dans
docker-compose.ymlou via les optionsdocker run. - [ ] Recréez uniquement le service affecté :
docker compose up -d <service>. - [ ] Surveillez les journaux pendant les 1 à 2 premières minutes :
docker compose logs -f <service>. - [ ] Vérifiez que le service passe les contrôles de santé s'ils sont définis :
docker inspect --format '{{.State.Health.Status}}' <container>.
Vérification post-changement
- [ ] Effectuez un test d'écriture et de lecture à l'intérieur du conteneur, par exemple
docker exec <container> sh -c "echo test > /data/testfile && cat /data/testfile". - [ ] Confirmez que le fichier existe sur l'hôte au point de montage du volume.
- [ ] Recréez le conteneur et vérifiez que le fichier persiste.
- [ ] Vérifiez les erreurs de permission dans le journal après le test d'écriture.
- [ ] Mettez à jour le manuel d'exploitation avec le changement et le résultat de la vérification.
Pièges courants et comment les éviter
Pourquoi cela arrive : Les équipes supposent qu'un simple changement de configuration est à faible risque et sautent l'étape de sauvegarde. Comment l'éviter : Intégrez la commande de sauvegarde dans la liste de vérification. Automatisez-la avec un script qui refuse de continuer si le fichier de sauvegarde n'est pas créé ou est vide.
- Ne pas sauvegarder avant de modifier les volumes
Pourquoi cela arrive : Le conteneur s'exécute initialement en tant que root, puis une mise à jour de sécurité change l'utilisateur en non-root. Les écritures échouent soudainement. Comment l'éviter : Testez toujours l'application avec le même utilisateur qu'en production. En CI, exécutez le conteneur exactement comme défini dans l'image ou le fichier Compose, y compris la directive user:.
- Ignorer les décalages de propriété de fichier
Pourquoi cela arrive : Les opérateurs veulent libérer rapidement de l'espace disque et exécutent la commande prune, supprimant par inadvertance des volumes qui ne sont pas actuellement utilisés mais contiennent des données importantes. Comment l'éviter : Listez d'abord les volumes en suspens avec docker volume ls -f dangling=true, inspectez chacun, puis supprimez uniquement les volumes explicites. Utilisez des étiquettes pour marquer les volumes critiques et les exclure avec --filter "label!=keep".
- Utiliser
docker volume prunesans filtres
Pourquoi cela arrive : Les deux montent un chemin hôte dans un conteneur, mais les montages de liaison exposent directement le système de fichiers hôte, ce qui entraîne des problèmes de permission et de portabilité. Comment l'éviter : Préférez les volumes nommés pour les données de production. Utilisez les montages de liaison uniquement lorsque vous avez besoin d'éditer en direct le code source pendant le développement.
- Supposer que les montages de liaison et les volumes nommés se comportent de la même manière
Pourquoi cela arrive : Les sauvegardes sont créées mais jamais restaurées, alors lorsqu'une panne réelle survient, la procédure de restauration échoue en raison de dépendances manquantes ou de chemins incorrects. Comment l'éviter : Planifiez un exercice trimestriel de reprise après sinistre. Le responsable (Priya Shah) est chargé d'exécuter l'exercice et de documenter le temps de restauration.
- Ne pas tester les procédures de récupération
Conclusion
Les volumes nommés Docker simplifient la persistance des données, mais ils nécessitent toujours une attention opérationnelle délibérée. Le flux de travail le plus fiable est d'observer avant de changer, de limiter chaque modification à un seul élément ciblé, de vérifier le résultat avec une commande concrète et d'avoir un plan de retour en arrière testé. Chaque étape de ce guide comprend une commande et sa sortie attendue afin que vous puissiez suivre dans votre propre environnement.
Commencez par l'inventaire des versions et de l'environnement pour comprendre votre base de référence. Traitez ensuite les changements de configuration comme des opérations réversibles avec sauvegardes. Lorsqu'une panne survient, utilisez les commandes de diagnostic pour déterminer si le volume est monté, si les permissions sont correctes et si les données persistent réellement. Enfin, adoptez la liste de vérification opérationnelle et attribuez un seul responsable pour la réviser régulièrement. Ainsi, les volumes nommés Docker deviennent une partie prévisible de votre infrastructure plutôt qu'une source de surprise.