infra / docker-compose
Volumes et persistance des données
Explication
Ce que vous allez apprendre
- Comprendre pourquoi les données écrites dans un conteneur disparaissent avec lui
- Choisir entre un volume nommé (persistance) et un bind mount (développement en direct)
- Éviter le piège des volumes anonymes qui s'accumulent silencieusement sur le disque
- Savoir que
docker compose downne supprime jamais les volumes nommés, sauf avec-v - Sécuriser un montage en lecture seule avec l'option
:ro
Dans quel contexte ?
Une équipe redémarre régulièrement sa stack de développement avec docker compose down puis up pour repartir d'un environnement propre. Un jour, elle réalise que toutes les données de test de la base app_db ont disparu après un simple redémarrage, alors qu'elle pensait le volume db_data persistant. Cette leçon explique précisément pourquoi, et comment éviter ce genre de surprise.
Le point de départ : ce qui disparaît
Par nature, un conteneur est éphémère. Tout ce qu'il écrit sur son propre système de fichiers disparaît dès qu'il est supprimé. Pour l'application elle-même, ce n'est pas grave : on veut justement pouvoir la recréer identique à volonté.
Il reste un problème : les données qu'on veut garder
Mais que se passe-t-il pour les données qu'on veut absolument conserver, comme le contenu d'une base de données ? Si elles vivent uniquement dans le conteneur, un simple redémarrage les efface. C'est là qu'interviennent les volumes.
Première solution : le volume nommé
Un volume nommé est un espace de stockage géré entièrement par Docker, qui existe en dehors du cycle de vie du conteneur. Tu ne sais généralement pas où il vit réellement sur le disque, et ce n'est pas grave : c'est le bon choix pour des données qui doivent survivre à un docker compose down puis up, comme les fichiers d'une base Postgres.
Deuxième solution : le bind mount
Une fois qu'on comprend le volume nommé, il faut connaître son cousin : le bind mount. Il relie directement un dossier de ta machine à un dossier du conteneur. C'est idéal en développement, car toute modification du code sur ta machine est immédiatement visible dans le conteneur, sans reconstruire l'image.
Bien choisir entre les deux
Pour résumer simplement : volume nommé pour des données à conserver durablement, bind mount pour du code que tu modifies en direct pendant le développement. Les deux peuvent d'ailleurs cohabiter sur un même service.
| Type de montage | Géré par | Survit à down (sans -v) | Cas d'usage typique |
|---|---|---|---|
| Volume nommé | Docker | Oui | Données Postgres, Redis persistant |
| Bind mount | Le système de fichiers hôte | Oui (c'est ton dossier) | Code source en développement |
| Volume anonyme | Docker, sans nom | Oui, mais introuvable | À éviter |
Un cas à éviter : le volume anonyme
Il existe une troisième forme, le volume anonyme, qui n'a pas de nom explicite, juste un chemin. Évite-le : sans nom, il devient vite impossible à identifier et s'accumule silencieusement sur le disque au fil du temps.
Le piège le plus dangereux de cette leçon
Beaucoup de débutants croient qu'un docker compose down supprime aussi les volumes nommés. C'est faux : il faut explicitement taper down -v pour cela. Ce piège classique a déjà fait perdre des données de test... et parfois de production.
Piège dangereux
docker compose down -v supprime IMMÉDIATEMENT et sans confirmation tous les volumes nommés du projet, y compris db_data. Ne l'utilise jamais par réflexe sur un environnement qui contient des données que tu veux garder — vérifie toujours d'abord avec docker volume ls ce qui va disparaître.
Un dernier réflexe de sécurité
Pense aussi à ajouter :ro (read-only) sur un montage qui ne devrait jamais être modifié par le conteneur : cela évite une brèche de sécurité inutile.
Bonne pratique
Avant toute opération risquée sur une base de données locale, sauvegarde le volume avec docker run --rm -v db_data:/data -v "$(pwd)":/backup alpine tar czf /backup/db_data.tar.gz -C /data .. Cette archive peut être restaurée plus tard, indépendamment du cycle de vie des conteneurs.
La prochaine leçon aborde un autre besoin fondamental : configurer une application différemment selon l'environnement, grâce aux variables d'environnement et aux fichiers .env.
Commandes & code
Volumes & persistance
Les conteneurs sont éphémères : sans volume, les données disparaissent avec le conteneur.
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: changeme
volumes:
# Volume nommé : géré par Docker, persiste entre les "down/up"
- db_data:/var/lib/postgresql/data
# Bind mount : mappe un dossier de l'hôte (utile en dev)
- ./init-scripts:/docker-entrypoint-initdb.d:ro
web:
image: nginx:1.27-alpine
volumes:
- ./html:/usr/share/nginx/html:ro # ro = read-only dans le conteneur
- nginx_cache:/var/cache/nginx
redis:
image: redis:7-alpine
volumes:
# Volume anonyme (pas de nom explicite) : évité en pratique
- /data
command: ["redis-server", "--appendonly", "yes"]
# Déclaration obligatoire des volumes nommés au niveau racine
volumes:
db_data:
driver: local
nginx_cache:# Lister les volumes créés par Docker
docker volume ls
# Inspecter un volume (point de montage réel sur l'hôte)
docker volume inspect docker-compose_db_data
# Supprimer les volumes orphelins (non référencés par un conteneur)
docker volume prune
# Sauvegarder un volume nommé dans une archive tar
docker run --rm -v docker-compose_db_data:/data -v "$(pwd)":/backup \
alpine tar czf /backup/db_data.tar.gz -C /data .| Type | Exemple | Cas d'usage |
|---|---|---|
| Volume nommé | db_data:/var/lib/postgresql/data | Données persistantes gérées par Docker |
| Bind mount | ./src:/app/src | Live reload en développement |
| Volume anonyme | /data | À éviter : difficile à retrouver/nettoyer |
:ro | ./conf:/etc/nginx:ro | Empêche le conteneur de modifier l'hôte |
Résumé
- Sans volume = perte de données au
downou à la recréation du conteneur. - Volumes nommés pour la persistance, bind mounts pour le dev en live.
- Toujours déclarer les volumes nommés sous la clé racine
volumes:.
Exercices pratiques
Mission : sauver les données de staging avant un nettoyage douteux
Objectif : Distinguer volume nommé, bind mount et option -v, et anticiper une suppression accidentelle de données.
Contexte
Sur l'environnement de staging de boutique-api, un collègue s'apprête à taper docker compose down -v en pensant que -v signifie simplement "verbose" (plus de détails affichés). Le service db utilise un volume nommé db_data, et le service web monte ./html en lecture seule sur /usr/share/nginx/html.
Vérifie ce qui va réellement se passer avant de laisser faire, et sécurise la configuration.