Changer le thème

Guide pratique des volumes Docker : 5 exemples pour ne plus perdre les données des conteneurs

Easton editorial illustration: environment switchboard

Dernière ligne du terminal : « Database import completed successfully ». Quatre heures pour importer vingt mille enregistrements de test dans un conteneur MySQL. Quelques appels API, les tests passent.

Le lendemain, reflexe : docker ps pour voir l’état. Vide. Oublié de le relancer hier soir ? docker ps -a. Rien non plus. Puis le souvenir : avant de dormir, pour libérer de l’espace disque, docker system prune -a.

Terminé. Toutes les données perdues. Vingt mille lignes, quatre heures de travail, remis à zéro.

4 h
Perte de données
Vingt mille enregistrements, quatre heures de travail, tout à refaire

Trois semaines avec Docker : conteneurs rapides, isolation propre — mais pas le talon d’Achille : un conteneur n’est pas fait pour stocker des données. Supprimez-le, les données partent ; redémarrez-le, la config revient à zéro.

Cet article propose cinq cas pratiques pour utiliser Docker Volume et sortir les données du conteneur, afin qu’elles ne suivent plus son cycle de vie.

La vérité sur la perte de données des conteneurs

Pourquoi supprimer un conteneur efface-t-il les données ?

Docker utilise un système de fichiers en couches. Imaginez un gâteau mille-feuilles : couche inférieure = image (lecture seule, partagée) ; couche supérieure = couche conteneur (écriture, propre à chaque instance). Fichiers créés, config modifiée, données importées : tout est écrit dans cette couche supérieure.

Point clé : à la suppression du conteneur, cette couche en écriture est détruite.

Vous doutez ? Essayez :

# Démarrer un conteneur Alpine et écrire un fichier
docker run -it --name test-container alpine sh
# Dans le conteneur
echo "données importantes" > /tmp/data.txt
exit

# Supprimer le conteneur
docker rm test-container

# Tenter de récupérer
docker run -it --name test-container alpine sh
cat /tmp/data.txt  # Erreur : No such file or directory

Les données disparaissent sans avertissement.

Le design est cohérent : les conteneurs visent les applications sans état. Nginx, serveur API — pas besoin de persistance, chaque démarrage est identique. Base de données, Redis, upload de fichiers ? Il faut garder les données.

La solution officielle Docker : Volume — données hors du conteneur, cycle de vie du conteneur et des données totalement découplés.

Qu’est-ce qu’un Volume ? Comment il sauve vos données

L’essence du Volume : un disque externe pour le conteneur

Un Volume, c’est comme brancher un disque au conteneur. Les données ne sont pas dans la couche du conteneur, mais dans un répertoire de l’hôte, monté dans le conteneur (par ex. /var/lib/mysql). En réalité : /var/lib/docker/volumes/mysql-data/_data sur l’hôte.

Conteneur supprimé ? Les données restent sur l’hôte. Nouveau conteneur, même Volume : tout revient.

Trois types de montage — faciles à confondre au début :

Type de montageEmplacement des donnéesCas d’usageGestion
VolumeRépertoire géré par Docker (/var/lib/docker/volumes/)Persistance BDD, prodCommandes docker volume
Bind MountChemin arbitraire sur l’hôteCode, config en devChemins manuels
tmpfsMémoireDonnées temporaires, sensibles (sans disque)Vidé à l’arrêt du conteneur

Au début, Volume et Bind Mount semblaient identiques (« monter un répertoire hôte »). Jusqu’au piège : Bind Mount sur le répertoire de données MySQL, suppression du dossier hôte — conteneur MySQL en panne.

Volume = gestion complète par Docker : pas de souci de chemins, permissions, stratégie de backup. Emplacement ? docker volume inspect. Migration ? commandes docker volume. D’où la recommandation officielle Volume plutôt que Bind Mount pour la persistance.

Où sont réellement les données Volume ?

Sur Linux, par défaut :

/var/lib/docker/volumes/<volume-name>/_data/

Sur Mac et Windows avec Docker Desktop, tout tourne dans une VM : ce chemin n’est pas visible localement. Utilisez docker volume inspect pour les détails.

5 exemples pour maîtriser les Volume

Assez de théorie — cinq cas du simple au réel. Faites-les une fois, vous aurez compris l’essentiel.


Exemple 1 : créer votre premier Volume nommé

Le plus simple : un Volume vide.

# Créer un Volume nommé my-data
docker volume create my-data

# Lister les Volume
docker volume ls

# Détails
docker volume inspect my-data

Sortie attendue (inspect) :

[
    {
        "CreatedAt": "2025-12-17T12:00:00Z",
        "Driver": "local",
        "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
        "Name": "my-data"
    }
]

Mountpoint : l’emplacement réel des données.


Exemple 2 : persistance d’un site statique Nginx

Scénario : site statique en dev, redémarrage Nginx à chaque modification — images et logs perdus à chaque fois.

Solution : monter /usr/share/nginx/html sur un Volume.

# Volume pour le contenu du site
docker volume create nginx-html

# Nginx avec Volume
docker run -d \
  --name my-nginx \
  -p 8080:80 \
  -v nginx-html:/usr/share/nginx/html \
  nginx:latest

# Page de test dans le conteneur
docker exec my-nginx bash -c 'echo "<h1>Hello Docker Volume!</h1>" > /usr/share/nginx/html/index.html'

# Test (navigateur http://localhost:8080 ou curl)
curl http://localhost:8080

Supprimez le conteneur :

docker rm -f my-nginx

Nouveau conteneur, même Volume :

docker run -d \
  --name my-nginx-v2 \
  -p 8080:80 \
  -v nginx-html:/usr/share/nginx/html \
  nginx:latest

# Le contenu est toujours là
curl http://localhost:8080

Rien n’est perdu. C’est ça, la magie du Volume.


Exemple 3 : persistance MySQL (niveau production)

Cas le plus courant : MySQL en conteneur, données obligatoirement persistantes.

# Volume dédié MySQL
docker volume create mysql-data

# Conteneur MySQL
docker run -d \
  --name mysql-demo \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \
  -e MYSQL_DATABASE=testdb \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# Attendre le démarrage (~10 s)
sleep 10

# Table de test
docker exec -it mysql-demo mysql -uroot -pmy-secret-pw testdb -e "
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50)
);
INSERT INTO users (name) VALUES ('Alice'), ('Bob');
"

# Lecture
docker exec -it mysql-demo mysql -uroot -pmy-secret-pw testdb -e "SELECT * FROM users;"

Suppression du conteneur (simulation d’erreur) :

docker rm -f mysql-demo

Relance avec le même Volume :

docker run -d \
  --name mysql-demo-v2 \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

sleep 10

# Les données sont toujours là
docker exec -it mysql-demo-v2 mysql -uroot -pmy-secret-pw testdb -e "SELECT * FROM users;"

Point clé : répertoire de données MySQL = /var/lib/mysql. Chemins différents selon le moteur : Redis /data, PostgreSQL /var/lib/postgresql/data.


Exemple 4 : persistance Redis

Redis stocke par défaut en mémoire ; RDB ou AOF permettent la persistance disque.

docker volume create redis-data

docker run -d \
  --name redis-demo \
  -p 6379:6379 \
  -v redis-data:/data \
  redis:latest redis-server --appendonly yes
  # --appendonly yes active l'AOF

docker exec -it redis-demo redis-cli SET mykey "Hello Redis Volume"

docker exec -it redis-demo redis-cli GET mykey

Suppression :

docker rm -f redis-demo

Relance :

docker run -d \
  --name redis-demo-v2 \
  -p 6379:6379 \
  -v redis-data:/data \
  redis:latest redis-server --appendonly yes

docker exec -it redis-demo-v2 redis-cli GET mykey

Attention : sans --appendonly yes, Redis ne persiste qu’en mémoire — redémarrage = perte malgré le Volume.


Exemple 5 : Volume partagé entre plusieurs conteneurs

Scénario : un conteneur Nginx sert des fichiers statiques, un autre écrit des logs — même Volume.

docker volume create shared-logs

# Conteneur applicatif qui écrit les logs
docker run -d \
  --name app-writer \
  -v shared-logs:/logs \
  alpine sh -c "while true; do echo $(date) >> /logs/app.log; sleep 2; done"

# Nginx en lecture seule
docker run -d \
  --name log-reader \
  -p 8080:80 \
  -v shared-logs:/usr/share/nginx/html:ro \
  nginx:latest
  # :ro = lecture seule (read-only)

sleep 5

curl http://localhost:8080/app.log

Points clés :

  1. Un Volume peut être monté sur plusieurs conteneurs
  2. Suffixe :ro pour le mode lecture seule
  3. En prod : architecture « conteneur de collecte de logs + conteneur applicatif »

Commandes de gestion des Volume

Après les cinq exemples : comment lister, supprimer, nettoyer ?

# 1. Créer
docker volume create <volume-name>

# 2. Lister
docker volume ls

# 3. Détails (chemin de montage)
docker volume inspect <volume-name>

# 4. Supprimer un Volume
docker volume rm <volume-name>
# Erreur si un conteneur l'utilise encore

# 5. Supprimer tous les Volume inutilisés
docker volume prune
# Confirmation : taper y

# 6. Forcer sans confirmation
docker volume prune -f

Problème courant : « volume is in use »

Un conteneur utilise encore ce Volume :

docker ps -a --filter volume=<volume-name>

docker rm -f <container-name>

docker volume rm <volume-name>

Espace disque occupé

# Linux/Mac
docker volume inspect <volume-name> --format '{{ .Mountpoint }}' | xargs du -sh

# Exemple : 512M    /var/lib/docker/volumes/mysql-data/_data

Bind Mount vs Volume : lequel choisir ?

Question classique des débutants. Règle simple : données de prod → Volume ; code de dev → Bind Mount.

ScénarioRecommandationRaison
MySQL / PostgreSQLVolumeGestion Docker, backup, perfs
Redis / MongoDBVolumeIdem
Logs, fichiers uploadésVolumeSécurité, survit à la suppression
Code source en devBind MountModifications immédiates sans rebuild
Config (nginx.conf)Bind MountÉdition rapide sur l’hôte
Cache, données temporairestmpfsRapide, pas de disque

Comparaison de syntaxe

# Volume (persistance recommandée)
docker run -v my-volume:/data redis:latest

# Bind Mount (dev)
docker run -v /Users/me/code:/app node:latest

# Syntaxe --mount (plus explicite, prod)
docker run --mount type=volume,source=my-volume,target=/data redis:latest
docker run --mount type=bind,source=/Users/me/code,target=/app node:latest

Arbre de décision

  1. Les données doivent-elles être conservées longtemps ? Oui → Volume ; non → tmpfs
  2. Faut-il les modifier directement sur l’hôte ? Oui → Bind Mount ; non → Volume
  3. Prod ou dev ? Prod → Volume ; dev → Bind Mount

Exemple réel

Environnement de dev :

docker run -d \
  --name dev-app \
  -v $(pwd)/src:/app/src \          # Bind Mount : code à jour tout de suite
  -v app-uploads:/app/uploads \     # Volume : fichiers uploadés
  -v postgres-data:/var/lib/postgresql/data \  # Volume : BDD
  my-app:dev

Production :

docker run -d \
  --name prod-app \
  -v app-uploads:/app/uploads \
  -v postgres-data:/var/lib/postgresql/data \
  my-app:latest
# Le code est dans l'image, pas de montage nécessaire

FAQ et bonnes pratiques

FAQ : pièges et solutions

Q1 : les données Volume peuvent-elles disparaître ?
Non, tant que vous n’exécutez pas docker volume rm. Même après redémarrage de l’hôte, les données restent.

Attention : docker system prune -a --volumes supprime tous les Volume inutilisés — à utiliser avec prudence.


Q2 : que se passe-t-il si le Volume n’existe pas au démarrage ?
Docker le crée automatiquement :

docker run -d -v auto-created-volume:/data alpine

Je recommande toutefois de créer le Volume explicitement pour savoir où sont les données.


Q3 : comment sauvegarder un Volume ?
Méthode recommandée :

docker run --rm \
  -v mysql-data:/source \
  -v $(pwd):/backup \
  alpine tar -czf /backup/mysql-backup.tar.gz -C /source .

# Restauration
docker run --rm \
  -v mysql-data:/target \
  -v $(pwd):/backup \
  alpine tar -xzf /backup/mysql-backup.tar.gz -C /target

Q4 : migrer un Volume entre machines ?
Oui, manuellement :

  1. Sur la machine source : archiver comme ci-dessus
  2. Transférer le .tar.gz
  3. Sur la nouvelle machine : créer le Volume et extraire

Pour aller plus loin : driver Volume NFS ou stockage cloud.


Q5 : volume anonyme ? Nettoyage ?
Sans nom explicite, Docker crée un volume anonyme :

docker run -d -v /data alpine  # nom aléatoire du type a1b2c3d4...

Difficile à gérer, risque de saturation disque :

docker volume prune  # supprime les Volume inutilisés, anonymes inclus

Bonne pratique : toujours un Volume nommé.


6 bonnes pratiques (production)

  1. Volume nommé systématiquement

    # ✓ Bon
    docker run -v mysql-data:/var/lib/mysql mysql:8.0
    
    # ✗ Mauvais
    docker run -v /var/lib/mysql mysql:8.0  # volume anonyme
  2. Sauvegardes régulières des données critiques
    Tâche planifiée quotidienne sur les Volume de BDD. Une perte de données, on n’oublie pas.

  3. Docker Compose pour les projets complexes

    # docker-compose.yml
    services:
      db:
        image: mysql:8.0
        volumes:
          - mysql-data:/var/lib/mysql
    
    volumes:
      mysql-data:
        driver: local
  4. En prod, préférer --mount à -v
    Syntaxe plus explicite, messages d’erreur plus clairs :

    docker run --mount type=volume,source=mysql-data,target=/var/lib/mysql mysql:8.0
  5. Nettoyer les Volume inutilisés
    Une fois par mois :

    docker volume prune
  6. Données sensibles : chiffrement
    Mots de passe, clés dans un Volume : envisager le chiffrement (ex. partition LUKS).

Conclusion

Retour à cette nuit-là — avec Docker Volume, une seule ligne aurait suffi :

docker run -d --name mysql-demo -v mysql-data:/var/lib/mysql mysql:8.0

Les données n’auraient pas suivi le conteneur dans la poubelle. Quatre heures de travail, vingt mille lignes, en sécurité sur l’hôte.

Les conteneurs Docker sont sans état — atout et limite. Le Volume existe pour dépasser cette limite : légèreté et isolation du conteneur, données persistantes en confiance.

Cinq exemples : premier Volume, Nginx, MySQL, Redis, partage multi-conteneurs — environ 90 % des besoins du quotidien.

À vous : terminal, premier Volume, conteneur MySQL, écrivez des données. Supprimez le conteneur, relancez — quand les données sont encore là, vous comprenez vraiment la persistance.

Et si vous ne voulez plus revivre la peur des 3 h du matin sans backup, gardez cet article sous la main. Un jour, il pourra vous sauver.

Parcours complet des volumes Docker en pratique

5 exemples pour éliminer la perte de données des conteneurs, du concept de base à MySQL et Redis

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Comprendre la cause : pourquoi les données des conteneurs disparaissent

    Cause du problème :
    • Un conteneur Docker n'est pas fait pour stocker des données ; supprimez-le et les données partent
    • Au redémarrage, la configuration revient à l'état d'origine
    • À la suppression, la couche en écriture est détruite avec le conteneur
    • C'est le talon d'Achille de Docker

    Système de fichiers en couches :
    • Couche inférieure : image (lecture seule, partagée par tous les conteneurs)
    • Couche supérieure : couche conteneur (écriture, propre à chaque conteneur)
    • Fichiers créés, config modifiée, données importées : tout est écrit dans cette couche supérieure
    • À la suppression du conteneur, cette couche en écriture est détruite
  2. 2

    Step 2: Cas 1 : créer votre premier Volume

    Créer un Volume :
    • docker volume create
    • Commande : docker volume create my-data
    • Géré par Docker, stocké dans le répertoire de données Docker — adapté à la production

    Utiliser le Volume :
    • Au démarrage : docker run -d -v my-data:/data alpine
    • Les données restent dans le Volume ; supprimez le conteneur, les données restent

    Vérifier :
    • docker volume ls pour lister
    • docker volume inspect my-data pour les détails
  3. 3

    Step 3: Cas 2 à 5 : Nginx, MySQL, Redis et partage multi-conteneurs

    Cas 2 : persistance d'un site statique Nginx
    • Monter le Volume : docker run -d -v nginx-html:/usr/share/nginx/html nginx
    • Les fichiers statiques restent dans le Volume après suppression du conteneur

    Cas 3 : persistance MySQL
    • Monter sur /var/lib/mysql : docker run -d -v mysql-data:/var/lib/mysql mysql:8.0
    • Les données de la base restent dans le Volume

    Cas 4 : persistance Redis
    • Monter sur /data : docker run -d -v redis-data:/data redis
    • Les données Redis restent dans le Volume

    Cas 5 : Volume partagé entre plusieurs conteneurs
    • Plusieurs conteneurs, même Volume :
    docker run -d -v shared-data:/data container1
    docker run -d -v shared-data:/data container2
    • Les conteneurs partagent les données
  4. 4

    Step 4: Volume vs Bind Mount et bonnes pratiques

    Volume vs Bind Mount :

    Volume
    • Géré par Docker, stocké dans le répertoire de données Docker
    • Adapté à la production, plus sûr et fiable

    Bind Mount
    • Monte directement un répertoire de l'hôte
    • Adapté au développement, plus flexible

    Bonnes pratiques :
    • Production : Volume
    • Développement : Bind Mount possible
    • Sauvegarder régulièrement :
    docker run --rm -v mysql-data:/data -v $(pwd):/backup alpine tar czf /backup/mysql-backup.tar.gz /data
    • Volume nommé pour faciliter la gestion ; éviter les volumes anonymes
    • Nettoyer les volumes inutilisés : docker volume prune une fois par mois

FAQ

Pourquoi les données des conteneurs disparaissent-elles ? Un conteneur n'est-il pas fait pour stocker des données ?
Cause : un conteneur Docker n'est pas fait pour stocker des données ; supprimez-le et les données partent, redémarrez-le et la config revient à zéro ; à la suppression, la couche en écriture est détruite — le talon d'Achille de Docker.

Docker utilise un système de fichiers en couches, comme un gâteau mille-feuilles :
• Couche inférieure : image (lecture seule, partagée)
• Couche supérieure : couche conteneur (écriture, propre à chaque conteneur)
• Fichiers, config, données importées : tout dans cette couche supérieure
• Suppression du conteneur : destruction de cette couche en écriture
Comment Docker Volume résout-il la perte de données ?
Solution : Docker Volume libère les données du conteneur pour qu'elles ne suivent plus son cycle de vie. Mécanisme de persistance fourni par Docker : données sur l'hôte, intactes après suppression du conteneur.

Créer un Volume :
• docker volume create my-data
• Géré par Docker, adapté à la production

Utiliser :
• docker run -d -v my-data:/data alpine
• Données dans le Volume ; suppression du conteneur sans perte
Comment configurer la persistance pour MySQL et Redis ?
MySQL :
• Monter sur /var/lib/mysql : docker run -d -v mysql-data:/var/lib/mysql mysql:8.0
• Données de la base dans le Volume

Redis :
• Monter sur /data : docker run -d -v redis-data:/data redis
• Données Redis dans le Volume

Vérifier :
• Supprimer puis recréer le conteneur : les données sont toujours là
• docker volume inspect pour l'emplacement
• Stockage sur l'hôte
Quelle différence entre Volume et Bind Mount ? Lequel choisir ?
Volume vs Bind Mount :

Volume :
• Géré par Docker, répertoire de données Docker
• Production : plus sûr et fiable

Bind Mount :
• Répertoire hôte direct
• Développement : plus flexible

Choix :
• Production → Volume (gestion Docker, plus sûr)
• Développement → Bind Mount (accès direct aux fichiers hôte, debug plus simple)

Bonnes pratiques :
• Production : Volume ; développement : Bind Mount possible
• Sauvegardes régulières
• Volume nommé ; éviter l'anonyme

10 min de lecture · Publié le: 17 déc. 2025 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog