Skip to content

TP4 : Manipuler des volumes avec Docker

Objectif du TP

  • Comprendre la persistance des données avec Docker (volumes nommés, bind mounts, volumes anonymes).
  • Savoir créer/inspecter/utiliser/supprimer un volume et migrer des données.
  • Pratiquer avec Nginx, MySQL et Adminer.

Rendu attendu

  • Commandes exécutées et captures d’écran (docker volume ls, inspect, etc.).
  • Brève explication du choix entre volume nommé et bind mount selon le contexte.

Questions d'ouverture

  • Quelles données doivent survivre à la recréation d’un conteneur et lesquelles peuvent être reconstruites ?
  • Dans votre projet, préféreriez-vous un volume nommé ou un bind mount pour le dev ? Et pour la prod ? Pourquoi ?

Nous avons vu comment créer et lancer un conteneur, ainsi que construire une image avec un Dockerfile.
Maintenant, intéressons-nous à la persistance des données dans un conteneur via les volumes.


Focus : Persistance et couches

Avant la pratique, revoyons l’OverlayFS et l’intérêt des volumes.

1.1 Fonctionnement du système de fichiers d’un conteneur Docker

Rappel : chaque conteneur est basé sur une image dont les couches (layers) sont en lecture seule, et Docker utilise un Union File System (OverlayFS par exemple) pour appliquer une couche en écriture au-dessus de l’image.

  • UnionFS : système de fichiers empilé.
  • Les modifications écrites par le conteneur restent dans la couche la plus haute.
  • Si on supprime le conteneur, ces modifications sont perdues, sauf si elles ont été externalisées dans un volume.

1.2 Comprendre la gestion des volumes


1.2.1 Différents types de volumes

  1. Volumes nommés (Named Volumes)
  2. Gérés entièrement par Docker.
  3. Créés via docker volume create monvolume.
  4. Montés par -v monvolume:/chemin/dans/le/conteneur.

  1. Bind mounts (dossier local)
  2. On spécifie un chemin local : -v /home/user/data:/chemin/dans/le/conteneur.
  3. Permet de travailler directement avec les fichiers sur la machine hôte.

  1. Volumes temporaires (Anonymous volumes)
  2. Créés automatiquement par Docker, sans nom spécifique.

Quand utiliser quel type de volume ?
- Named volumes : pour persister les données des applications en production (ex. : bases de données).
- Bind mounts : pour un environnement de développement (modifications locales visibles immédiatement).
- Anonymous volumes : pour des tests rapides ou des cas où la persistance n’est pas nécessaire.


1.2.2 Créer, inspecter, migrer et supprimer un volume

Tableau récapitulatif des commandes docker volume :

Commande Description
docker volume create monvolume Crée un volume nommé
docker volume ls Liste tous les volumes
docker volume inspect monvolume Affiche les détails d’un volume
docker volume rm monvolume Supprime un volume
docker volume prune Supprime tous les volumes non utilisés

  • Migrer un volume : utiliser un conteneur temporaire pour copier les données :
    docker run --rm \
      -v source_volume:/data1 \
      -v target_volume:/data2 \
      alpine sh -c "cp -r /data1/* /data2/"
    

1.3 Sécurité et options avancées

  • Pour protéger un bind mount en lecture seule :
    -v /path:/containerpath:ro
    

Mise en pratique

1.4 Exercice 1 : persister un site statique

  1. Créer un volume :
    docker volume create myhtml
    

  1. Créer un fichier index.html localement :
<html>
<head><title>Encore un fichier HTML bidon</title></head>
<body>
 <h1>Bravo Damien, mais on en a marre un peu non ?</h1>
</body>
</html>

  1. Lancer un conteneur avec le volume :
docker run -d \
 --name volumetest \
 -p 80:80 \
 -v myhtml:/usr/share/nginx/html \
 nginx:alpine

  • Copier le fichier dans le volume :

    docker cp index.html volumetest:/usr/share/nginx/html
    

  • Modifier le fichier puis recopiez-le dans le volume.

  • La page web a-t-elle changé ?

  1. Tester la persistance :
  2. Supprimez et recréez le conteneur. La page est toujours accessible à http://localhost.

1.5 Exercice 2 : utiliser un bind mount

  1. Créer un dossier local nommé webcontent avec un index.html :
<html>
<head><title>Encore un fichier HTML bidon</title></head>
<body>
 <h1>Bravo Damien, mais on en a marre un peu non ?</h1>
</body>
</html>

  1. Lancer le conteneur avec le bind mount :
docker run -d \
 --name bindtest \
 -p 80:80 \
 -v $(pwd)/webcontent:/usr/share/nginx/html \
 nginx:alpine

  1. Modifier le fichier index.html local et rafraîchir la page web :

  2. Les changements sont visibles immédiatement.


1.6 Exercice 3 : Volumes avec MySQL et Adminer

Attention - Évitez --link (obsolète). Préférez un réseau utilisateur dédié (ex. docker network create dbnet) et connectez-y vos services. - Sur Apple Silicon, vérifiez que l’image choisie supporte arm64 (ou utilisez MariaDB si besoin).

  1. Lancer un conteneur MySQL avec un volume nommé :
docker network create dbnet

docker run -d \
  --name mysqltest \
  --network dbnet \
  -e MYSQL_ROOT_PASSWORD=root \
  -v mysql_data:/var/lib/mysql \
  mysql:8

  1. Ajouter un conteneur Adminer pour gérer facilement la base de données :
docker run -d \
  --name adminer \
  --network dbnet \
  -p 8080:8080 \
  adminer

Le conteneur Adminer utilise le réseau Docker pour se connecter à MySQL via le nom du conteneur (mysqltest).


  1. Accéder à Adminer :
  2. Ouvrez un navigateur à l’adresse http://localhost:8080.
  3. Connectez-vous avec les informations suivantes :
    • Serveur : mysqltest (le nom du conteneur MySQL sur le réseau dbnet).
    • Utilisateur : root.
    • Mot de passe : root.
    • Base de données : laissez vide (vous pouvez en créer une depuis Adminer).

  1. Créer une table et insérer des données :
  2. Une fois connecté, créez une base de données appelée testdb.
  3. Naviguez dans cette base de données et créez une table users avec les colonnes suivantes :
    • id (int, clé primaire, auto-incrémentée).
    • name (varchar).
    • email (varchar).
  4. Insérez quelques lignes dans la table via l’interface d’Adminer.

  1. Vérifier la persistance des données :

  2. Supprimez le conteneur MySQL :

    docker stop mysqltest
    docker rm mysqltest
    


  • Relancez un nouveau conteneur MySQL avec le même volume :
    docker run -d \
      --name mysqltest \
      --network dbnet \
      -e MYSQL_ROOT_PASSWORD=root \
      -v mysql_data:/var/lib/mysql \
      mysql:8
    

Utilisez cette fois CloudBeaver pour vous reconnecter à la base de données et vérifier que les données insérées précédemment sont toujours présentes.


1.7 Exercice 4 : Ghost CMS

Profitez de ce TP pour installer Ghost, un CMS basé sur Node.js, avec une base de données MySQL. Le but est de prendre en main Ghost et de faire le tour de l'outil.

Allez sur l'image Ghost sur Docker Hub puis lisez la documentation pour savoir comment la lancer avec une base de données MySQL.


Aide :

# 1) Créez un réseau dédié
docker network [à vous de compléter]

# 2) Lancez MySQL/MariaDB sur ce réseau (exemple MySQL)
docker run -d \
  --name ghostdb \
  --network [à vous de compléter] \
  -e MYSQL_ROOT_PASSWORD=changeme \
  -e MYSQL_DATABASE=ghost \
  -e MYSQL_USER=ghost \
  -e MYSQL_PASSWORD=changeme \
  -v ghost_db:/var/lib/mysql \
  mysql:8

# 3) Lancez Ghost sur le même réseau
docker run -d \
  --name ghostcms \
  --network ghostnet \
  -p 2368:2368 \
  -e url=http://localhost:2368 \
  -e database__client=mysql \
  -e database__connection__host=ghostdb \
  -e database__connection__user=ghost \
  -e database__connection__password=changeme \
  -e database__connection__database=ghost \
  -v ghost_content:/var/lib/ghost/content \
  ghost:latest

Pensez à aller sur http://localhost:???/ghost/ pour configurer votre blog.


Conclusion

  • Vous savez persister des données avec volumes nommés et bind mounts.
  • Vous avez pratiqué sur Nginx, MySQL + Adminer et découvert un cas réel (Ghost).