Docker Compose, Volumes & Bonnes Pratiques
Docker Compose permet de gérer plusieurs containers en un seul fichier YAML. Les volumes persistent les données au-delà du cycle de vie des containers.
Docker Compose
Pourquoi Docker Compose ?
Lancer plusieurs containers avec docker run devient vite complexe :
# Sans Docker Compose — long et difficile à maintenir
docker run -d \
--name mongo \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
--net mongo-network \
mongo
docker run -d \
--name mongo-express \
-p 8081:8081 \
-e ME_CONFIG_MONGODB_ADMINUSERNAME=admin \
-e ME_CONFIG_MONGODB_ADMINPASSWORD=password \
-e ME_CONFIG_MONGODB_SERVER=mongodb \
--net mongo-network \
mongo-express
Avec Docker Compose : tout est défini dans un seul fichier YAML lisible.
Structure d'un docker-compose.yaml
version: '3'
services:
mongodb:
image: mongo
ports:
- 27017:27017
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=password
volumes:
- db-data:/var/lib/mysql/data
mongo-express:
image: mongo-express
ports:
- 8080:8081
environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=admin
- ME_CONFIG_MONGODB_ADMINPASSWORD=password
- ME_CONFIG_MONGODB_SERVER=mongodb
volumes:
db-data:
Points clés :
- Docker Compose crée automatiquement un réseau commun pour tous les services — ils peuvent se contacter par leur nom de service (ex:
mongodb) - Remplace l'option
--netdedocker run - Les
environmentremplacent-e - Les
portsremplacent-p
Commandes Docker Compose
docker compose up -d # Démarrer tous les services en arrière-plan
docker compose down # Arrêter et supprimer les containers
docker compose down -v # + supprimer les volumes
docker compose logs # Afficher les logs de tous les services
docker compose logs -f # Suivre les logs en temps réel
docker compose ps # Lister les services et leur état
docker compose build # Rebuilder les images (si Dockerfile défini)
docker compose up --build -d # Rebuild + démarrer
Docker Volumes
Pourquoi les volumes ?
Par défaut, les données d'un container sont stockées dans son système de fichiers virtuel. Quand le container est supprimé → les données sont perdues.
Sans volume :
docker rm mongo → toutes les données MongoDB supprimées !
Avec volume :
docker rm mongo → données sauvegardées sur l'hôte
docker run mongo → données restaurées automatiquement
Cas d'usage critiques : bases de données, applications stateful.
Comment les volumes fonctionnent
Hôte (physique) Container
───────────────── ──────────────────────────
/home/mount/data ◄──montage──► /var/lib/mysql/data
(virtual file system)
Un dossier du système de fichiers hôte est monté dans le système de fichiers virtuel du container. Les données sont automatiquement synchronisées dans les deux sens.
Les 3 Types de Volumes
1. Host Volume — Volume hôte
Vous définissez vous-même le chemin sur l'hôte :
docker run -v /home/mount/data:/var/lib/mysql/data mongo
Hôte: /home/mount/data ◄──► Container: /var/lib/mysql/data
2. Anonymous Volume — Volume anonyme
Docker génère automatiquement un chemin sur l'hôte (hash aléatoire) :
docker run -v /var/lib/mysql/data mongo
Hôte: /var/lib/docker/volumes/<random-hash>/_data ◄──► Container: /var/lib/mysql/data
Inconvénient : difficile à retrouver et référencer.
3. Named Volume — Volume nommé (recommandé en production)
Vous donnez un nom au volume — Docker gère l'emplacement sur l'hôte :
docker run -v db-data:/var/lib/mysql/data mongo
Hôte: /var/lib/docker/volumes/db-data/_data ◄──► Container: /var/lib/mysql/data
Avantage : référençable par nom, partageable entre plusieurs containers.
Comparaison des 3 types
| Type | Syntaxe | Chemin hôte | Recommandé |
|---|---|---|---|
| Host | -v /host/path:/container/path | Défini par vous | Dev |
| Anonymous | -v /container/path | Hash aléatoire auto | Non |
| Named | -v nom:/container/path | Géré par Docker | Production |
Volumes dans Docker Compose
version: '3'
services:
mongodb:
image: mongo
ports:
- 27017:27017
volumes:
- db-data:/var/lib/mysql/data # ← Named Volume
mongo-express:
image: mongo-express
# ...
volumes: # ← Déclarer les named volumes ici
db-data: # Docker crée et gère ce volume
Le même volume db-data peut être partagé entre plusieurs services dans le même fichier Compose.
Bonnes Pratiques Docker
Sécurité
| Pratique | Raison |
|---|---|
| Utiliser des images officielles/fiables | Éviter les malwares dans les images tiers |
| Spécifier les versions exactes | Éviter les surprises avec latest |
| Utiliser des images minimales (alpine) | Surface d'attaque réduite + image plus légère |
| Créer un utilisateur dédié dans l'image | Ne pas faire tourner l'app en root dans le container |
| Scanner les images | Détecter les vulnérabilités (docker scan, Trivy) |
| Ne pas mettre de secrets dans l'image | Passer via variables d'env ou secrets managers |
# Exemple : utilisateur dédié (least privilege)
FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /home/app
COPY . .
RUN npm install
USER appuser # ← Basculer sur l'utilisateur non-root
CMD ["node", "server.js"]
Optimisation de la taille
# Préférer alpine (beaucoup plus léger)
FROM node:20-alpine # ~180MB
# vs
FROM node:20 # ~1.1GB
# Utiliser .dockerignore
# node_modules/, .git/, *.log, .env
# Optimiser l'ordre des layers pour le cache
COPY package.json .
RUN npm install # cache tant que package.json ne change pas
COPY . . # code source copié en dernier
Multi-Stage Builds (Dockerfiles propres)
Pour éviter d'inclure les outils de build dans l'image finale :
# Stage 1 : Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
# Stage 2 : Production (image finale légère)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
L'image finale ne contient que les fichiers nécessaires à l'exécution, pas les outils de build.
À retenir
- Docker Compose = fichier YAML pour définir et lancer plusieurs containers ensemble
- Docker Compose crée automatiquement un réseau commun — les services communiquent par leur nom
docker compose up -d/docker compose down- Volume = mécanisme pour persister les données au-delà du cycle de vie d'un container
- 3 types : Host (chemin défini), Anonymous (hash auto), Named (recommandé en production)
- Déclarer les named volumes dans la section
volumes:du docker-compose.yaml- Bonnes pratiques : images officielles/alpine, versions figées, utilisateur non-root, .dockerignore
- Multi-Stage Build : séparer build et runtime pour des images de production légères