infra / docker
Volumes et bind mounts
Explication
Ce que vous allez apprendre
- Comprendre pourquoi un conteneur est éphémère et pourquoi ses données disparaissent sans précaution
- Distinguer un volume nommé (géré par Docker) d'un bind mount (chemin hôte explicite)
- Choisir la bonne solution de persistance selon le contexte (production, développement, données sensibles)
- Sauvegarder et restaurer un volume nommé à l'aide d'un conteneur intermédiaire
- Éviter le piège classique de chercher en vain le contenu d'un volume directement sur le disque hôte
Dans quel contexte ?
Une équipe déploie une base PostgreSQL en conteneur pour la première fois. Après quelques jours de tests concluants, elle supprime le conteneur par erreur avec docker rm -f db pour libérer de l'espace — et découvre que toutes les données créées ont disparu avec lui, car aucun volume n'avait été monté sur /var/lib/postgresql/data. Une leçon apprise à ses dépens qu'un volume nommé aurait évitée du premier coup.
Le problème que résout cette leçon
Un conteneur est par nature éphémère : tout ce qu'il écrit dans son propre système de fichiers disparaît définitivement dès qu'il est supprimé (docker rm). C'est très bien pour une application sans état, mais catastrophique pour une base de données ou tout ce qui doit survivre à un redémarrage. Il faut donc un moyen de faire persister des données en dehors du cycle de vie du conteneur.
| Type | Géré par | Cas d'usage typique |
|---|---|---|
| Volume nommé | Docker | Bases de données, données persistantes en prod |
| Bind mount | Toi (chemin hôte explicite) | Développement, hot-reload de code |
| tmpfs | RAM, jamais sur disque | Secrets temporaires, cache volatile |
Prérequis
Il est utile d'être à l'aise avec le cycle de vie de base d'un conteneur (docker run, docker rm) vu dans la première leçon.
Deux façons de persister, deux philosophies
Un volume est un espace de stockage entièrement géré par Docker : on lui donne un nom, et Docker s'occupe de l'emplacement réel sur le disque. C'est la solution recommandée en production, car elle est portable, indépendante du système de fichiers de l'hôte et plus facile à sauvegarder ou migrer.
Un bind mount, à l'inverse, relie un chemin précis et connu de la machine hôte à un chemin dans le conteneur. C'est très pratique en développement : en montant le dossier source du projet, on peut modifier son code depuis son éditeur habituel et voir le changement pris en compte immédiatement dans le conteneur, sans reconstruire l'image à chaque fois.
Il existe une troisième option, plus rare : tmpfs, un stockage qui vit uniquement en mémoire RAM et n'est jamais écrit sur disque — utile pour des données sensibles ou temporaires qui ne doivent laisser aucune trace.
Le piège à connaître
Un volume nommé n'est pas directement consultable comme un simple dossier depuis l'hôte : il faut passer par un conteneur intermédiaire pour y accéder (par exemple pour faire une sauvegarde).
Piège fréquent
Beaucoup de débutants cherchent en vain le dossier du volume sur leur disque, alors qu'il est géré en interne par Docker dans un emplacement qu'il vaut mieux ne jamais manipuler directement. Pour sauvegarder ou inspecter son contenu, passe toujours par un conteneur temporaire qui le monte (voir l'exemple avec alpine + tar), jamais en fouillant directement /var/lib/docker/volumes.
Lien avec la suite
Cette notion de persistance sera reprise telle quelle dans Docker Compose (leçon 8), où chaque service pourra déclarer ses propres volumes de façon déclarative.
Commandes & code
Volumes et bind mounts
# Un conteneur est éphémère : ses données disparaissent avec lui SAUF si elles sont persistées.
# --- Volumes Docker : gérés par Docker lui-même, recommandés en production ---
docker volume create data_postgres
docker volume ls
docker volume inspect data_postgres
docker volume rm data_postgres
docker run -d --name db -v data_postgres:/var/lib/postgresql/data postgres:16
# La partie gauche (data_postgres) est un volume nommé, géré par Docker (pas un chemin hôte)
# --- Bind mounts : lie un chemin PRÉCIS de l'hôte à un chemin du conteneur ---
docker run -d --name api -v /home/ned/mon-api/src:/app/src mon-api:1.0
# Utile en développement (hot-reload du code sans reconstruire l'image)
docker run -d --name api -v "$(pwd)":/app -w /app mon-api:1.0 npm run dev
# Syntaxe --mount (plus explicite, préférée en production, équivalente à -v)
docker run -d --name db \
--mount type=volume,source=data_postgres,target=/var/lib/postgresql/data \
postgres:16
docker run -d --name api \
--mount type=bind,source=/home/ned/mon-api/src,target=/app/src,readonly \
mon-api:1.0
# readonly empêche le conteneur d'écrire dans le dossier source de l'hôte
# tmpfs : stockage en mémoire RAM, jamais écrit sur disque (données sensibles/temporaires)
docker run -d --name cache --tmpfs /app/cache:size=100m mon-api:1.0
# Backup d'un volume nommé (le volume n'est pas directement accessible depuis l'hôte)
docker run --rm -v data_postgres:/data -v "$(pwd)":/backup alpine \
tar czf /backup/postgres-backup.tar.gz -C /data .
# Restauration d'un volume à partir d'un backup
docker run --rm -v data_postgres:/data -v "$(pwd)":/backup alpine \
tar xzf /backup/postgres-backup.tar.gz -C /data
# Voir quel(s) conteneur(s) utilisent un volume donné avant de le supprimer
docker ps -a --filter volume=data_postgres| Type | Géré par | Emplacement | Cas d'usage |
|---|---|---|---|
| Volume nommé | Docker | /var/lib/docker/volumes/... | bases de données, données persistantes en prod |
| Bind mount | Toi (chemin hôte explicite) | n'importe où sur l'hôte | développement, config, hot-reload |
| tmpfs | RAM, jamais sur disque | mémoire | secrets temporaires, cache volatile |
Résumé
- Sans volume, toute donnée écrite dans un conteneur disparaît à sa suppression.
- Les volumes nommés sont gérés par Docker et recommandés en production ; les bind mounts pointent un chemin hôte précis.
- Un volume se sauvegarde en passant par un conteneur intermédiaire (
alpine+tar) qui le monte.
Exercices pratiques
Mission : sécuriser une base PostgreSQL avant une purge de conteneurs
Objectif : Mettre en place la persistance correcte d'une base de données et savoir en extraire une sauvegarde.
Contexte
Une équipe s'apprête à lancer docker container prune pour nettoyer un serveur de test, mais une base PostgreSQL tourne dedans sans volume. Tu dois d'abord sécuriser ses données avant tout nettoyage.