Les volumes Docker : persister ses données
Un conteneur Docker est éphémère par nature : tout ce qu’il écrit dans son système de fichiers disparaît dès qu’on le supprime. Pour une base de données, des fichiers uploadés par des utilisateurs ou des logs, cette amnésie est inacceptable. Les volumes résolvent le problème en stockant les données hors du cycle de vie du conteneur. Ce guide détaille les trois mécanismes de stockage, comment les créer et les monter, comment sauvegarder puis restaurer, et les bonnes pratiques autour des bases de données.
Pourquoi les données d’un conteneur disparaissent
Chaque conteneur possède une couche d’écriture propre, empilée au-dessus des couches en lecture seule de son image. Quand vous exécutez docker rm, cette couche est détruite avec le conteneur. Redémarrer le même conteneur conserve les données ; le supprimer les efface définitivement.
Les volumes contournent cette logique en montant un espace de stockage géré séparément à un emplacement précis du conteneur. Les écritures y sont dirigées et survivent au conteneur.
Les trois types de stockage
Docker propose trois mécanismes, à choisir selon l’usage.
Named volumes (volumes nommés)
Un volume nommé est entièrement géré par Docker, stocké dans une zone dédiée de l’hôte (/var/lib/docker/volumes/ sous Linux). C’est le choix recommandé pour les données de production, notamment les bases de données.
# Créer un volume nommé
docker volume create donnees-app
# Lister les volumes
docker volume ls
# Inspecter un volume (emplacement, driver, date)
docker volume inspect donnees-app
Bind mounts (montages liés)
Un bind mount relie un dossier précis de votre machine hôte à un dossier du conteneur. Vous contrôlez le chemin exact côté hôte. C’est idéal en développement : votre code modifié est immédiatement visible dans le conteneur.
# Monter le dossier courant dans /app du conteneur
docker run -d -v $(pwd):/app mon-app
Contrairement au volume nommé, un bind mount dépend de la structure de fichiers de l’hôte, ce qui le rend moins portable mais très pratique pour l’édition à chaud.
tmpfs
Un montage tmpfs stocke les données uniquement en mémoire vive, jamais sur disque. Elles disparaissent à l’arrêt du conteneur. On l’utilise pour des données sensibles ou temporaires (secrets déchiffrés, fichiers de cache) qu’on ne veut surtout pas persister.
# Monter un espace tmpfs en mémoire
docker run -d --tmpfs /app/cache mon-app
Créer et monter un volume
Deux syntaxes coexistent. La forme courte -v est concise ; la forme longue --mount est plus explicite et recommandée dans les scripts.
# Syntaxe courte : volume nommé
docker run -d -v donnees-app:/data mon-app
# Syntaxe longue équivalente
docker run -d \
--mount type=volume,source=donnees-app,target=/data \
mon-app
# Bind mount en lecture seule (ro)
docker run -d \
--mount type=bind,source="$(pwd)"/config,target=/etc/app,readonly \
mon-app
L’ajout de readonly (ou :ro en syntaxe courte, par exemple -v $(pwd)/config:/etc/app:ro) empêche le conteneur de modifier le contenu monté : utile pour des fichiers de configuration.
Avec Docker Compose
Dans un fichier docker-compose.yml, les volumes nommés se déclarent dans une section dédiée puis se référencent par service. Notre guide de Docker Compose par l’exemple détaille toute la structure du fichier.
services:
db:
image: postgres:16
volumes:
- donnees-db:/var/lib/postgresql/data
volumes:
donnees-db:
Cas d’usage : une base de données
C’est le scénario le plus fréquent. Chaque image de base de données écrit ses fichiers à un emplacement précis, qu’il faut monter sur un volume nommé.
# PostgreSQL : les données vivent dans /var/lib/postgresql/data
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16
# MySQL / MariaDB : /var/lib/mysql
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-v mysqldata:/var/lib/mysql \
mysql:8
# MongoDB : /data/db
docker run -d \
--name mongo \
-v mongodata:/data/db \
mongo:7
Grâce au volume, vous pouvez supprimer et recréer le conteneur (mise à jour de version, changement de configuration) sans perdre une seule ligne de données.
Sauvegarder ses données
Un volume géré par Docker ne s’ouvre pas directement dans l’explorateur de fichiers. La technique consiste à lancer un conteneur temporaire qui monte à la fois le volume et un dossier de l’hôte, puis à créer une archive.
# Sauvegarder le volume "pgdata" dans une archive locale
docker run --rm \
-v pgdata:/data \
-v $(pwd):/backup \
alpine \
tar czf /backup/pgdata-backup.tar.gz -C /data .
Décortiquons : --rm supprime le conteneur après usage, -v pgdata:/data monte le volume à sauvegarder, -v $(pwd):/backup monte le dossier courant, et tar compresse le contenu de /data dans l’archive côté /backup.
Pour une base de données, une alternative plus fiable est d’utiliser l’outil de dump natif, qui garantit un état cohérent :
# Dump SQL d'une base PostgreSQL en conteneur
docker exec postgres pg_dump -U postgres production > sauvegarde.sql
Restaurer ses données
La restauration inverse l’opération : on décompresse l’archive dans un volume neuf.
# Recréer le volume au besoin
docker volume create pgdata
# Restaurer le contenu de l'archive dans le volume
docker run --rm \
-v pgdata:/data \
-v $(pwd):/backup \
alpine \
tar xzf /backup/pgdata-backup.tar.gz -C /data
Pour un dump SQL, on réinjecte le fichier dans la base :
# Restaurer un dump PostgreSQL
cat sauvegarde.sql | docker exec -i postgres psql -U postgres production
Testez toujours vos restaurations sur un environnement de test : une sauvegarde qu’on n’a jamais restaurée n’est qu’une hypothèse.
Nettoyer les volumes inutilisés
Les volumes orphelins, créés par des conteneurs supprimés, s’accumulent et consomment de l’espace disque.
# Lister les volumes non utilisés
docker volume ls -f dangling=true
# Supprimer un volume précis (par son nom, jamais en masse)
docker volume rm ancien-volume
# Supprimer tous les volumes non référencés (destructif)
docker volume prune
Maniez docker volume prune avec prudence : il efface tous les volumes qu’aucun conteneur n’utilise, y compris des données que vous auriez pu vouloir garder.
Bonnes pratiques
- Volumes nommés pour la production, bind mounts pour le développement. Les premiers sont portables et gérés par Docker ; les seconds facilitent l’édition à chaud.
- Ne stockez jamais de données critiques dans la couche du conteneur. Tout ce qui doit survivre passe par un volume.
- Automatisez les sauvegardes et vérifiez régulièrement qu’elles se restaurent réellement.
- Utilisez le mode lecture seule (
:ro) pour tout ce que le conteneur ne doit pas modifier, comme la configuration. - Privilégiez les dumps natifs (
pg_dump,mysqldump) pour les bases de données, plus fiables qu’une archive brute des fichiers. - Documentez vos volumes dans le
docker-compose.yml: c’est votre inventaire des données à protéger.
En résumé
Les volumes sont la réponse de Docker à la nature éphémère des conteneurs. En choisissant le bon type — nommé, bind mount ou tmpfs — et en mettant en place une routine de sauvegarde et de restauration, vous faites tourner des bases de données et des applications à état en toute sérénité. La prochaine étape consiste à orchestrer plusieurs services persistants ensemble, ce que Docker Compose rend simple.