Pourquoi un conteneur perd ses données au redémarrage

Écrivez une ligne dans une base de données qui tourne dans un conteneur Docker, arrêtez le conteneur, relancez-le : la ligne a disparu.

Chaque conteneur reçoit son système de fichiers neuf depuis son image à chaque démarrage. Tout ce que le conteneur écrit lui-même — fichiers de base de données, uploads, logs — va dans une couche accessible en écriture qui est jetée quand le conteneur est supprimé. Un volume Docker sert à garder ces données hors du conteneur, là où elles survivent.

Qu’est-ce qu’un volume Docker ?

Un volume Docker est un mécanisme pour sauvegarder les données en dehors du conteneur, de sorte qu’elles persistent même lorsque le conteneur est arrêté, redémarré ou supprimé.

Pensez aux volumes comme à un disque dur externe que vous connectez à votre conteneur. Les données sont écrites sur ce “disque externe” et restent en sécurité indépendamment de ce qui arrive au conteneur.

Pourquoi utiliser les volumes ?

  • Persistance : les données survivent au cycle de vie du conteneur
  • Partage : plusieurs conteneurs peuvent accéder aux mêmes données
  • Sauvegarde : il est plus facile de faire des sauvegardes des données
  • Performance : les volumes sont optimisés pour les opérations I/O
  • Portabilité : vous pouvez déplacer les données entre différents hôtes

Volumes, bind mounts et tmpfs : lequel choisir

Il y a trois façons de persister des données, dans l’ordre où il faut les envisager : volumes, bind mounts, tmpfs.

1. Volumes - le choix recommandé

Les volumes sont entièrement gérés par Docker et sauvegardés dans un répertoire spécial sur l’hôte (/var/lib/docker/volumes/ sur Linux).

1
2
3
4
5
# Créer un volume
docker volume create mon-volume

# Utiliser le volume dans un conteneur
docker run -v mon-volume:/app/data mon-image

Avantages :

  • Gérés par Docker (faciles à créer, supprimer, inspecter)
  • Fonctionnent sur Linux, Windows et Mac
  • Peuvent être partagés entre plusieurs conteneurs
  • Supportent des drivers pour le stockage distant (cloud, NFS, etc.)

2. Bind mounts - connexion directe

Les bind mounts connectent un dossier spécifique de votre ordinateur directement au conteneur.

1
2
# Connecter un dossier local au conteneur
docker run -v /chemin/sur/votre/pc:/app/data mon-image

Quand les utiliser :

  • Pendant le développement, pour voir les modifications du code en temps réel
  • Quand vous avez besoin d’accéder à des fichiers spécifiques du système hôte
  • Pour partager des configurations entre l’hôte et le conteneur

Attention : les bind mounts dépendent de la structure du système de fichiers de l’hôte, ils sont donc moins portables.

3. tmpfs - données temporaires en mémoire

Les tmpfs mounts sauvegardent les données dans la RAM de l’hôte, pas sur le disque.

1
docker run --tmpfs /app/temp mon-image

Quand les utiliser :

  • Pour des données sensibles qui ne doivent pas être écrites sur le disque
  • Pour des caches temporaires à hautes performances
  • Les données sont perdues quand le conteneur s’arrête (et c’est exactement ce que vous voulez)

Commandes de volume Docker : create, list, inspect, remove

Créer un volume

1
docker volume create nom-volume

Lister les volumes

1
docker volume ls

Inspecter un volume

1
docker volume inspect nom-volume

Cette commande montre où le volume est physiquement sauvegardé et d’autres informations utiles.

Supprimer un volume

1
2
3
4
5
# Supprimer un volume spécifique
docker volume rm nom-volume

# Supprimer tous les volumes non utilisés
docker volume prune

Attention : supprimer un volume signifie perdre toutes les données contenues. Il n’y a pas de corbeille ni de récupération.

Exemples de volume Docker : base de données, dev en live-reload, partage

Exemple 1 : base de données MySQL avec données persistantes

Sans volume, chaque fois que vous redémarrez le conteneur MySQL, vous perdez toutes les données. Voici comment résoudre ce problème :

1
2
3
4
5
6
7
8
9
# Créer un volume pour les données MySQL
docker volume create mysql-data

# Démarrer MySQL en utilisant le volume
docker run -d \
  --name mon-mysql \
  -e MYSQL_ROOT_PASSWORD=password123 \
  -v mysql-data:/var/lib/mysql \
  mysql:8

Maintenant, vous pouvez arrêter, redémarrer ou même supprimer et recréer le conteneur : les données de la base de données resteront intactes dans le volume mysql-data.

Exemple 2 : développement web avec bind mount

Pendant le développement, vous voulez que les modifications du code soient immédiatement visibles dans le conteneur :

1
2
3
4
5
docker run -d \
  --name mon-site \
  -p 8080:80 \
  -v $(pwd)/src:/var/www/html \
  php:apache

Chaque modification des fichiers dans le dossier src sera immédiatement disponible dans le conteneur.

Exemple 3 : partager des données entre conteneurs

Deux conteneurs qui doivent accéder aux mêmes fichiers :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Créer le volume partagé
docker volume create donnees-partagees

# Conteneur qui écrit
docker run -d --name ecrivain -v donnees-partagees:/data alpine \
  sh -c "while true; do date >> /data/log.txt; sleep 5; done"

# Conteneur qui lit
docker run -it --name lecteur -v donnees-partagees:/data alpine \
  tail -f /data/log.txt

Volumes dans Docker Compose

Dans Docker Compose, vous déclarez les volumes une fois et chaque service qui en a besoin les référence par leur nom :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
version: '3.8'

services:
  database:
    image: postgres:15
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret

  app:
    image: mon-app
    volumes:
      - ./code:/app              # Bind mount pour le développement
      - logs:/app/logs           # Volume pour les logs

volumes:
  postgres-data:    # Volume géré par Docker
  logs:             # Volume géré par Docker

Avec un simple docker-compose up, Docker crée automatiquement les volumes nécessaires.

Sauvegarder et restaurer un volume Docker

Sauvegarder un volume

1
2
3
4
docker run --rm \
  -v nom-volume:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/backup.tar.gz -C /source .

Cette commande :

  1. Monte le volume en lecture seule (ro)
  2. Crée une archive compressée dans le répertoire actuel

Restaurer une sauvegarde

1
2
3
4
docker run --rm \
  -v nom-volume:/target \
  -v $(pwd):/backup \
  alpine tar xzf /backup/backup.tar.gz -C /target

Erreurs à éviter avec les volumes Docker

1. Oublier le volume pour une base de données

Si vous utilisez une base de données dans Docker sans volume, vous perdrez toutes les données. Toujours.

2. Utiliser des bind mounts en production

Les bind mounts sont excellents pour le développement, mais en production, utilisez les volumes Docker pour plus de portabilité et de sécurité.

3. Ne pas sauvegarder les volumes

Les volumes ne sont pas automatiquement inclus dans les sauvegardes du système. Planifiez des sauvegardes régulières.

4. Accumuler des volumes orphelins

Quand vous supprimez des conteneurs, les volumes restent. Utilisez périodiquement :

1
docker volume prune

Pour supprimer les volumes qui ne sont plus connectés à aucun conteneur.

Quelle option de stockage pour quel usage

ScénarioSolution
Base de données en productionVolume Docker
Développement localBind mount
Données sensibles temporairestmpfs
Partage entre conteneursVolume Docker
Fichiers de configurationBind mount ou Volume
Logs d’applicationVolume Docker

La règle qui couvre la plupart des cas

Utilisez un volume nommé pour tout ce qu’un conteneur écrit et que vous voulez conserver, les bases de données en premier. Utilisez un bind mount quand vous voulez que le conteneur voie un dossier de votre machine pendant que vous l’éditez, c’est-à-dire surtout en développement local. Gardez tmpfs pour les données qui ne doivent jamais toucher le disque.

Une fois qu’une base de données a un volume, vous pouvez supprimer et recréer son conteneur autant de fois que vous voulez : les données restent en place. C’est tout l’intérêt.

Articles associés