Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 612 minIntermédiaire

Volumes Docker : conserver les données

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • choisir entre volume nommé, montage de dossier et tmpfs ;
  • faire tourner une base de données dont les données survivent au conteneur ;
  • corriger un problème de permissions sur un dossier monté ;
  • sauvegarder et restaurer une base et un volume.

4 exercices corrigés

Un volume Docker est un espace de stockage géré par Docker, monté dans un conteneur, qui survit à la suppression du conteneur : c'est là que vont les données qui doivent durer, comme les fichiers d'une base de données. Ce chapitre compare les trois façons de monter du stockage (volume nommé, montage de dossier et tmpfs), installe une base MySQL persistante, explique les pièges de permissions et montre comment sauvegarder et restaurer un volume.

Pourquoi les données disparaissent

Tout ce qu'un conteneur écrit hors d'un montage va dans sa couche inscriptible, qui est supprimée avec lui. Lance une base sans volume, crée une table, supprime et recrée le conteneur : la table a disparu. Or on supprime et recrée les conteneurs en permanence : à chaque mise à jour d'image, à chaque changement de configuration.

La règle : un conteneur doit pouvoir être détruit à tout moment sans perte. Les données qui comptent vivent dans un volume ; tout le reste est reconstructible à partir de l'image.

Trois façons de monter du stockage

TypeOù sont les donnéesUsage type
Volume nomméUn dossier géré par Docker, /var/lib/docker/volumes/<nom>/_dataLes données d'un service : base de données, fichiers déposés par les utilisateurs
Montage de dossier (bind mount)Un dossier ou un fichier précis de l'hôte, choisi par toiUn fichier de configuration, un certificat, le code source en développement
tmpfsEn mémoire vive, jamais sur disqueDes fichiers temporaires, avec un système de fichiers de conteneur en lecture seule

Deux syntaxes existent pour docker run : la courte, -v, et la longue, --mount, plus lisible et plus stricte.

bash
# Volume nommé
docker run -d --name bdd -v mysql-donnees:/var/lib/mysql mysql:8.4
docker run -d --name bdd --mount type=volume,source=mysql-donnees,target=/var/lib/mysql mysql:8.4

# Montage d'un fichier en lecture seule
docker run -d -v /srv/gestion/Caddyfile:/etc/caddy/Caddyfile:ro caddy:2.11
docker run -d --mount type=bind,source=/srv/gestion/Caddyfile,target=/etc/caddy/Caddyfile,readonly caddy:2.11

# tmpfs
docker run -d --mount type=tmpfs,target=/tmp nginx:1.30-alpine

Avec -v, Docker décide seul : si la partie gauche est un nom, c'est un volume ; si c'est un chemin absolu, c'est un montage de dossier, et si le dossier n'existe pas, Docker le crée vide, ce qui masque souvent une faute de frappe. --mount type=bind refuse un chemin qui n'existe pas : l'erreur saute aux yeux.

Gérer les volumes nommés

bash
docker volume create mysql-donnees
docker volume ls
docker volume inspect mysql-donnees
docker volume rm mysql-donnees      # refusé si un conteneur l'utilise
json
[
    {
        "CreatedAt": "2026-11-03T10:02:41+01:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/mysql-donnees/_data",
        "Name": "mysql-donnees",
        "Options": null,
        "Scope": "local"
    }
]

Un volume monté pour la première fois sur un dossier qui contient déjà des fichiers dans l'image reçoit une copie de ces fichiers. Un montage de dossier, lui, masque le contenu de l'image à cet endroit.

Une base MySQL persistante

bash
docker volume create gestion-mysql
docker run -d --name gestion-bdd \
  --restart unless-stopped \
  -e MYSQL_ROOT_PASSWORD='Test-Labo-2026!' \
  -e MYSQL_DATABASE=frais \
  -v gestion-mysql:/var/lib/mysql \
  mysql:8.4

Au premier démarrage, l'image initialise la base dans le volume vide et crée la base frais. Supprime le conteneur (docker rm -f gestion-bdd) et relance la même commande : MySQL retrouve ses fichiers dans le volume, les données sont intactes, et les variables d'initialisation sont ignorées puisque la base existe déjà.

Chaque image range ses données à un endroit précis, à lire dans sa documentation sur Docker Hub :

ImageDossier à monter
mysql:8.4, mariadb:11.8/var/lib/mysql
postgres:18/var/lib/postgresql (et non plus /var/lib/postgresql/data, comme jusqu'à la version 17)
mongo:8.0/data/db
caddy:2.11/data (certificats) et /config

Monter un dossier : configuration et développement

Le montage de dossier sert surtout à deux choses.

Fournir un fichier de configuration sans reconstruire l'image, en lecture seule :

bash
docker run -d --name proxy \
  -v /srv/gestion/Caddyfile:/etc/caddy/Caddyfile:ro \
  caddy:2.11

Développer : le code de ton poste est monté dans le conteneur, et chaque modification est visible tout de suite, sans reconstruire l'image. C'est pratique en développement, à proscrire en production, où le code doit être dans l'image, testée et versionnée.

Le piège des permissions. Un montage de dossier garde les propriétaires numériques de l'hôte. Si le processus du conteneur tourne sous l'UID 1000 et que le dossier de l'hôte appartient à root, l'application reçoit EACCES: permission denied. Corrige le propriétaire du dossier côté hôte (sudo chown -R 1000:1000 /srv/gestion/stockage), plutôt que de faire tourner le conteneur en root.

Sauvegarder et restaurer

Pour une base de données, fais un export logique, cohérent même si la base travaille pendant la sauvegarde. Le client de l'image fait le travail ; la redirection écrit le fichier sur l'hôte :

bash
docker exec gestion-bdd sh -c 'exec mysqldump --single-transaction --databases frais -uroot -p"$MYSQL_ROOT_PASSWORD"' \
  > /srv/sauvegardes/frais-$(date +%F).sql

La restauration envoie le fichier au client mysql du conteneur :

bash
docker exec -i gestion-bdd sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' \
  < /srv/sauvegardes/frais-2026-11-03.sql

Les options de mysqldump sont détaillées dans le chapitre Sauvegarder une base.

Pour des fichiers ordinaires (documents déposés, configuration), archive le volume avec un conteneur jetable qui le monte en lecture seule :

bash
docker run --rm \
  -v gestion-fichiers:/source:ro \
  -v /srv/sauvegardes:/sauvegarde \
  alpine:3.24 tar -czf /sauvegarde/fichiers-$(date +%F).tar.gz -C /source .

Et pour restaurer dans un volume vide :

bash
docker run --rm \
  -v gestion-fichiers:/cible \
  -v /srv/sauvegardes:/sauvegarde:ro \
  alpine:3.24 tar -xzf /sauvegarde/fichiers-2026-11-03.tar.gz -C /cible

Des volumes sur le stockage de l'entreprise

Le pilote local peut aussi monter un partage réseau NFS ou SMB comme volume : les données sont alors sur le NAS de l'entreprise, sauvegardées et protégées par ses instantanés, et le conteneur peut redémarrer sur un autre hôte. C'est utile pour des fichiers ; pour une base de données, un disque local (ou un disque iSCSI) reste préférable, car les bases supportent mal les latences et les verrous des partages réseau. Le stockage en réseau, NFS, SMB et iSCSI, est traité côté serveur dans le cours Stockage et NAS avec TrueNAS, et l'instantané de la VM entière dans le cours Virtualisation.

Exercices

Exercice 1 sur 4 Choisir le montage Réussi À revoir

Pour chaque besoin de l'application de gestion, choisis entre volume nommé, montage de dossier et tmpfs.

  1. Les fichiers de la base MySQL.
  2. Le Caddyfile du reverse proxy, modifié par les administrateurs.
  3. Les justificatifs (PDF) déposés par les salariés.
  4. Le dossier /tmp d'une API dont le système de fichiers est en lecture seule.
  5. Le code source pendant le développement sur le poste de la développeuse.
Voir la réponseMasquer la réponse de l'exercice 1
  1. Volume nommé : données d'un service, gérées par Docker.
  2. Montage de dossier, en lecture seule (:ro) : un fichier de configuration que l'on édite sur l'hôte et que l'on versionne.
  3. Volume nommé : des données qui doivent survivre au conteneur et être sauvegardées.
  4. tmpfs : des fichiers temporaires, en mémoire, qui n'ont pas à survivre.
  5. Montage de dossier : les modifications du code sont visibles immédiatement dans le conteneur, sans reconstruire l'image.

Tu avais trouvé ?

Exercice 2 sur 4 La base qui repart à zéro Réussi À revoir

Un technicien a lancé MySQL avec docker run -d --name bdd -e MYSQL_ROOT_PASSWORD=… mysql:8.4. Après docker rm -f bdd et la même commande docker run, toutes les tables ont disparu. Explique et corrige. Les données sont-elles récupérables ?

Voir la réponseMasquer la réponse de l'exercice 2

Aucun volume nommé n'était monté. L'image MySQL déclare VOLUME /var/lib/mysql : Docker a créé un volume anonyme pour le premier conteneur. docker rm -f bdd (sans -v) ne l'a pas supprimé, mais le nouveau conteneur a reçu un nouveau volume anonyme, vide.

Les données sont probablement récupérables : docker volume ls liste les volumes anonymes, et docker volume inspect donne leur date de création. On relance alors MySQL en montant l'ancien volume, puis on fait un export. Si quelqu'un a lancé docker volume prune entre-temps, elles sont perdues.

Correction : toujours nommer le volume : -v gestion-mysql:/var/lib/mysql.

Tu avais trouvé ?

Exercice 3 sur 4 Passer à PostgreSQL 18 Réussi À revoir

Un collègue modifie son déploiement de postgres:17 à postgres:18 en gardant le montage -v pg-donnees:/var/lib/postgresql/data. Le conteneur ne démarre plus correctement. Explique les deux problèmes.

Voir la réponseMasquer la réponse de l'exercice 3
  1. Le chemin de montage : depuis la version 18, l'image range les données dans un sous-dossier propre à la version, sous /var/lib/postgresql. Il faut monter le dossier parent : -v pg-donnees:/var/lib/postgresql.
  2. Le changement de version majeure : PostgreSQL 18 ne sait pas ouvrir directement les fichiers de données d'un PostgreSQL 17. Il faut migrer : exporter avec pg_dumpall depuis l'ancien conteneur, démarrer PostgreSQL 18 sur un nouveau volume, puis importer (ou utiliser pg_upgrade). Sauvegarde d'abord, toujours.

Tu avais trouvé ?

Exercice 4 sur 4 Écrire la sauvegarde Réussi À revoir

Écris la commande qui archive le volume wiki-donnees dans /srv/sauvegardes/wiki-AAAA-MM-JJ.tar.gz (date du jour), sans risque de modifier le volume.

Voir la réponseMasquer la réponse de l'exercice 4
bash
docker run --rm \
  -v wiki-donnees:/source:ro \
  -v /srv/sauvegardes:/sauvegarde \
  alpine:3.24 tar -czf /sauvegarde/wiki-$(date +%F).tar.gz -C /source .

Le :ro monte le volume en lecture seule : l'archivage ne peut rien y modifier. $(date +%F) est remplacé par le shell de l'hôte avant le lancement, par exemple wiki-2026-11-03.tar.gz. Si le wiki utilise une base de données, ajoute un export logique de la base : l'archive des fichiers ne suffit pas.

Tu avais trouvé ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Réseaux Docker : bridge, DNS interne et publication de portsRevoir le sommaire du cours