published: true
tags: docker, devops, mysql, beginners
cover_image:
canonical_url:
Docker Volumes : pourquoi tes données disparaissent (et comment les protéger pour de bon)
Le piège dans lequel je suis tombé (et toi aussi, probablement)
Voici une expérience que je te conseille de faire toi-même, une seule fois, pour bien comprendre la leçon.
docker run -d --name mysql-demo -e MYSQL_ROOT_PASSWORD=secret mysql:8.0
Tu te connectes, tu crées une table clients, tu insères 3 lignes. Tu vérifies : tout est là.
Puis :
docker rm -f mysql-demo
docker run -d --name mysql-demo -e MYSQL_ROOT_PASSWORD=secret mysql:8.0
Tu te reconnectes :
SELECT * FROM clients;
-- ERROR 1146 (42S02): Table 'shop.clients' doesn't exist
Tout a disparu. Pas un bug. Pas une erreur de manipulation. C'est exactement comme ça que Docker est censé fonctionner — et c'est précisément pour ça que les volumes existent.
Dans cet article, je t'explique pourquoi ça arrive, et comment je l'ai résolu avec un projet complet simulant l'infrastructure d'une PME (base de données, fichiers clients, sessions).
Pourquoi Docker "oublie" tout par défaut
Un container Docker repose sur un système de fichiers en couches, appelé OverlayFS. Schématiquement :
┌─────────────────────────────────┐
│ COUCHE D'ÉCRITURE (container) │ ← temporaire
├─────────────────────────────────┤
│ COUCHES DE L'IMAGE (lecture │ ← permanentes
│ seule) │
└─────────────────────────────────┘
L'image (lecture seule) contient le système et les binaires — elle ne change jamais. Quand tu lances un container, Docker ajoute une couche d'écriture par-dessus, où vivent tous les fichiers créés ou modifiés pendant l'exécution.
Le problème : docker rm détruit cette couche d'écriture. Et comme rien n'a été écrit ailleurs, tout part avec elle.
L'analogie qui m'a aidé à vraiment comprendre : l'image est un livre imprimé. La couche d'écriture est un post-it collé dessus. Tu jettes le post-it → tes notes disparaissent, mais le livre reste intact. Le livre, ici, c'est l'image — jamais affectée par la suppression d'un container.
Les 3 solutions, et quand utiliser laquelle
1. Named Volume — pour les données critiques
Un named volume est un espace de stockage entièrement géré par Docker. Tu lui donnes un nom, Docker s'occupe du reste.
services:
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Quand l'utiliser : toute base de données (MySQL, Postgres, MongoDB...). C'est la protection minimale non-négociable pour n'importe quelle donnée que tu ne peux pas te permettre de perdre.
Preuve que ça fonctionne :
docker compose down # supprime les containers, PAS le volume
docker compose up -d # les données sont toujours là
2. Bind Mount — pour les fichiers accessibles depuis le serveur
Un bind mount connecte un dossier de ta machine hôte directement à un dossier du container. Les deux dossiers sont littéralement le même dossier, vu depuis deux côtés différents.
services:
app:
image: nginx:alpine
user: "1000:1000"
volumes:
- ./uploads:/usr/share/nginx/html/uploads
Quand l'utiliser : fichiers uploadés par les utilisateurs, fichiers de configuration, code source en développement.
⚠️ Le piège classique : un fichier créé depuis l'intérieur du container appartient à root par défaut. Si ton script de déploiement tourne avec un utilisateur normal, il ne pourra pas le supprimer ou le modifier. La ligne user: "1000:1000" (ton UID Linux, trouvable avec la commande id) résout ce problème en alignant les permissions.
3. tmpfs — pour les données sensibles et temporaires
Un tmpfs est un espace de stockage qui vit exclusivement en RAM. Il n'est jamais écrit sur disque, et il disparaît automatiquement à l'arrêt du container.
services:
app:
tmpfs:
- /tmp/sessions:size=64m,mode=1777
Quand l'utiliser : tokens de session, secrets temporaires, cache haute performance non-critique.
Pourquoi c'est important pour la sécurité : si un token de session n'existe qu'en RAM, il ne peut pas être lu via un backup disque ou un accès physique malveillant au serveur. C'est le même principe utilisé par des outils comme HashiCorp Vault pour la gestion de secrets.
Le tableau de décision
| Besoin | Type à utiliser |
|---|---|
| Base de données | Named Volume |
| Fichiers uploadés / configuration | Bind Mount |
| Code source en dev (hot-reload) | Bind Mount |
| Sessions / secrets temporaires | tmpfs |
| Cache rapide non-critique | tmpfs |
Et si le volume lui-même est supprimé ? (Backup & Restore)
Un named volume protège contre la suppression du container. Mais que se passe-t-il si le volume lui-même est supprimé, ou si le serveur entier est perdu ?
C'est là qu'intervient la sauvegarde. Comme Docker cache l'emplacement réel d'un named volume, on ne peut pas simplement faire un cp. La technique standard consiste à utiliser un container Alpine temporaire qui sert de pont entre le volume et un dossier de backup :
docker run --rm \
-v db_data:/data:ro \
-v $(pwd)/backups:/backups \
alpine \
tar czf /backups/db_backup_$(date +%Y%m%d_%H%M%S).tar.gz -C /data .
Et pour restaurer après une suppression totale du volume :
docker volume create db_data
docker run --rm \
-v db_data:/data \
-v $(pwd)/backups:/backups:ro \
alpine \
tar xzf /backups/db_backup_20260615.tar.gz -C /data
J'ai testé cette procédure de bout en bout : suppression volontaire du volume, puis restauration complète. Toutes les données sont revenues, exactement comme avant le sinistre.
La stack finale
Le projet complet assemble 3 services représentant une infrastructure réaliste de PME :
- App (nginx) → Bind Mount pour les uploads + tmpfs pour les sessions
- MySQL → Named Volume pour la base de données
- Redis → Named Volume + tmpfs pour le cache
Avec un healthcheck pour fiabiliser le démarrage, un utilisateur dédié non-root pour la base de données (principe du moindre privilège), et une politique de redémarrage automatique.
Le code complet est disponible sur GitHub (lien à ajouter).
Ce que j'en retiens
Comprendre les volumes Docker, ce n'est pas mémoriser trois commandes. C'est comprendre que le cycle de vie d'un container et le cycle de vie d'une donnée sont deux choses complètement différentes. Un container est jetable par design — c'est même ce qui rend Docker puissant (scalabilité, mises à jour sans risque, reproductibilité). Une donnée, elle, ne l'est pas.
Une fois ce modèle mental posé, le choix entre Named Volume, Bind Mount et tmpfs n'est plus une question de mémorisation — c'est une question de bon sens appliqué au bon contexte.
Je documente mon apprentissage du Cloud et du DevOps, avec un focus sur des projets réalistes plutôt que des tutoriels abstraits. Si ce genre de contenu t'intéresse, n'hésite pas à me suivre.
Top comments (0)