Volumes Docker
Objectifs du chapitre
- Comprendre la persistance des données dans Docker
- Maîtriser les différents types de volumes
- Gérer les volumes efficacement
- Partager des données entre conteneurs
1 - Pourquoi les volumes ?
Le problème de l'éphémérité
Par défaut, les données d'un conteneur sont perdues à sa suppression :
# Créer un fichier dans un conteneur
docker run -it --name test ubuntu bash
echo "Hello" > /data.txt
exit
# Redémarrer le conteneur - fichier présent
docker start -i test
cat /data.txt # Hello
# Supprimer le conteneur - fichier perdu !
docker rm test
docker run -it ubuntu cat /data.txt # Erreur !
Les solutions
┌─────────────────────────────────────────────────────────────┐
│ Options de stockage │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Volumes │ │ Bind Mounts │ │ tmpfs │ │
│ │ (Géré par │ │ (Dossier │ │ (Mémoire RAM) │ │
│ │ Docker) │ │ hôte) │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
2 - Types de stockage
Comparaison
| Type | Emplacement | Gestion | Usage |
|---|---|---|---|
| Volume | /var/lib/docker/volumes/ | Docker | Production, données persistantes |
| Bind mount | N'importe où sur l'hôte | Utilisateur | Développement, configs |
| tmpfs | Mémoire RAM | Docker | Données temporaires sensibles |
Schéma
┌─────────────────────────────────────────────────────────────┐
│ Conteneur │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ /app/data │ │
│ └────────────────────────┬────────────────────────────┘ │
└───────────────────────────┼─────────────────────────────────┘
│
┌───────────────────┼ ───────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Volume │ │ Bind Mount │ │ tmpfs │
│ /var/lib/ │ │ /home/user/ │ │ (RAM) │
│ docker/vol/ │ │ project/data │ │ │
└───────────────┘ └───────────────┘ └───────────────┘
3 - Volumes Docker
Créer un volume
# Créer un volume
docker volume create mon-volume
# Créer avec options
docker volume create --driver local \
--opt type=none \
--opt device=/path/to/data \
--opt o=bind \
mon-volume
Lister les volumes
# Lister tous les volumes
docker volume ls
# Filtrer
docker volume ls --filter "dangling=true"
docker volume ls --filter "driver=local"
# Format personnalisé
docker volume ls --format "{{.Name}}: {{.Driver}}"
Inspecter un volume
# Détails d'un volume
docker volume inspect mon-volume
# Sortie JSON
{
"Name": "mon-volume",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/mon-volume/_data",
"Labels": {},
"Scope": "local"
}
Supprimer des volumes
# Supprimer un volume
docker volume rm mon-volume
# Supprimer plusieurs volumes
docker volume rm vol1 vol2 vol3
# Supprimer les volumes non utilisés
docker volume prune
# Forcer la suppression
docker volume prune -f
4 - Utiliser les volumes
Syntaxe avec -v
# Volume nommé
docker run -v mon-volume:/app/data nginx
# Volume anonyme
docker run -v /app/data nginx
# Mode lecture seule
docker run -v mon-volume:/app/data:ro nginx
Syntaxe avec --mount (recommandée)
# Volume nommé
docker run --mount source=mon-volume,target=/app/data nginx
# Avec options
docker run --mount type=volume,source=mon-volume,target=/app/data,readonly nginx
# Volume anonyme
docker run --mount type=volume,target=/app/data nginx
Exemples pratiques
# Base de données PostgreSQL avec volume
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
--mount source=pg-data,target=/var/lib/postgresql/data \
postgres:15
# Les données survivent à la suppression du conteneur
docker rm -f postgres
docker run -d \
--name postgres-new \
-e POSTGRES_PASSWORD=secret \
--mount source=pg-data,target=/var/lib/postgresql/data \
postgres:15
# Les données sont préservées !
5 - Bind Mounts
Syntaxe
# Avec -v
docker run -v /chemin/hote:/chemin/conteneur nginx
docker run -v $(pwd)/html:/usr/share/nginx/html nginx
# Avec --mount
docker run --mount type=bind,source=/chemin/hote,target=/chemin/conteneur nginx
# Lecture seule
docker run --mount type=bind,source=$(pwd)/config,target=/etc/nginx,readonly nginx
Cas d'usage : développement
# Monter le code source pour le hot-reload
docker run -d \
--name dev-app \
-p 3000:3000 \
-v $(pwd)/src:/app/src \
-v $(pwd)/package.json:/app/package.json \
node:18 npm run dev
# Les modifications du code sont reflétées immédiatement
Différences avec les volumes
| Aspect | Volume | Bind Mount |
|---|---|---|
| Emplacement | Géré par Docker | Spécifié par l'utilisateur |
| Portabilité | Excellent | Dépend du chemin hôte |
| Performance | Optimisée | Variable |
| Backup | Via Docker | Manuel |
| Sécurité | Meilleure isolation | Accès au système hôte |
6 - tmpfs Mounts
Usage
Le tmpfs stocke les données en mémoire RAM :
# Créer un tmpfs mount
docker run --mount type=tmpfs,target=/app/temp nginx
# Avec options
docker run --mount type=tmpfs,target=/app/temp,tmpfs-size=100m,tmpfs-mode=1777 nginx
Cas d'usage
- Données sensibles (secrets, tokens)
- Cache temporaire
- Fichiers de session
- Données qui ne doivent pas persister
# Stocker des secrets temporairement
docker run -d \
--name secure-app \
--mount type=tmpfs,target=/run/secrets \
mon-app
7 - Partager des données entre conteneurs
Volumes partagés
# Conteneur 1 : écrit des données
docker run -d \
--name writer \
--mount source=shared-data,target=/data \
alpine sh -c "while true; do date >> /data/log.txt; sleep 1; done"
# Conteneur 2 : lit les données
docker run -it \
--name reader \
--mount source=shared-data,target=/data,readonly \
alpine tail -f /data/log.txt
Volumes-from (legacy)
# Créer un conteneur avec des volumes
docker run -d --name data-container -v /data alpine sleep infinity
# Utiliser les volumes d'un autre conteneur
docker run --volumes-from data-container alpine ls /data
8 - Backup et restauration
Sauvegarder un volume
# Méthode 1 : tar dans un conteneur temporaire
docker run --rm \
-v mon-volume:/source:ro \
-v $(pwd):/backup \
alpine tar cvf /backup/mon-volume-backup.tar -C /source .
# Méthode 2 : docker cp (depuis un conteneur)
docker cp mon-conteneur:/app/data ./backup/
Restaurer un volume
# Créer le volume
docker volume create mon-volume-restored
# Restaurer depuis le backup
docker run --rm \
-v mon-volume-restored:/target \
-v $(pwd):/backup \
alpine tar xvf /backup/mon-volume-backup.tar -C /target
Script de backup automatisé
#!/bin/bash
# backup-volumes.sh
BACKUP_DIR="/backups/docker"
DATE=$(date +%Y%m%d_%H%M%S)
for volume in $(docker volume ls -q); do
echo "Backing up $volume..."
docker run --rm \
-v $volume:/source:ro \
-v $BACKUP_DIR:/backup \
alpine tar cvf /backup/${volume}_${DATE}.tar -C /source .
done
# Nettoyer les backups de plus de 7 jours
find $BACKUP_DIR -name "*.tar" -mtime +7 -delete
9 - Volumes dans Dockerfile
Instruction VOLUME
FROM node:18
WORKDIR /app
# Déclarer un volume
VOLUME /app/data
VOLUME ["/app/logs", "/app/uploads"]
COPY . .
CMD ["node", "server.js"]
Comportement
# Un volume anonyme est créé automatiquement
docker run mon-app
# Lister les volumes anonymes
docker volume ls
# DRIVER VOLUME NAME
# local abc123def456...
Attention
Les VOLUME dans le Dockerfile créent des volumes anonymes difficiles à gérer. Préférez les volumes nommés au runtime.
10 - Bonnes pratiques
Nommage
# ✅ Bon : noms descriptifs
docker volume create postgres-data
docker volume create app-uploads
docker volume create nginx-logs
# ❌ Mauvais : noms génériques
docker volume create data
docker volume create vol1
Sécurité
# Lecture seule quand possible
docker run --mount source=config,target=/etc/app,readonly mon-app
# Utilisateur non-root
docker run -u 1000:1000 --mount source=data,target=/app/data mon-app
Performance
# Utiliser des volumes pour les données fréquemment accédées
# (meilleure performance que bind mounts sur macOS/Windows)
# Pour le développement sur macOS
docker run -v mycode:/app:cached node:18 npm run dev
Nettoyage régulier
# Identifier les volumes orphelins
docker volume ls -f dangling=true
# Nettoyer
docker volume prune
# Vérifier l'espace utilisé
docker system df -v | grep VOLUME -A 100
Résumé
| Commande | Description |
|---|---|
docker volume create | Créer un volume |
docker volume ls | Lister les volumes |
docker volume inspect | Détails d'un volume |
docker volume rm | Supprimer un volume |
docker volume prune | Nettoyer les volumes inutilisés |
-v ou --mount | Monter un volume |
| Type | Usage recommandé |
|---|---|
| Volume | Données de production |
| Bind mount | Développement |
| tmpfs | Données temporaires/sensibles |
Points clés
- Les volumes persistent après suppression des conteneurs
- Utilisez
--mountpour une syntaxe claire - Nommez vos volumes de manière descriptive
- Sauvegardez régulièrement vos volumes critiques
Exercices pratiques
- Créez un volume et utilisez-le avec un conteneur MySQL
- Montez un dossier local pour le développement d'une app Node.js
- Partagez un volume entre deux conteneurs
- Effectuez un backup et une restauration d'un volume