Docker Compose
Objectifs du chapitre
- Comprendre Docker Compose et son utilité
- Écrire des fichiers docker-compose.yml
- Gérer des applications multi-conteneurs
- Maîtriser les commandes Compose
1 - Introduction à Docker Compose
Qu'est-ce que Docker Compose ?
Docker Compose est un outil pour définir et exécuter des applications multi-conteneurs.
Au lieu de :
docker network create myapp
docker run -d --name db --network myapp -e POSTGRES_PASSWORD=secret postgres:15
docker run -d --name redis --network myapp redis:7
docker run -d --name web --network myapp -p 3000:3000 -e DB_HOST=db myapp
Vous écrivez :
# docker-compose.yml
services:
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
redis:
image: redis:7
web:
image: myapp
ports:
- "3000:3000"
environment:
DB_HOST: db
Installation
Docker Compose est inclus avec Docker Desktop. Sur Linux :
# Vérifier l'installation
docker compose version
# Si nécessaire, installer le plugin
sudo apt-get install docker-compose-plugin
2 - Structure du fichier docker-compose.yml
Structure de base
# Version (optionnel depuis Compose v2)
version: "3.9"
# Définition des services
services:
service1:
image: image1
# configuration...
service2:
build: ./path
# configuration...
# Volumes nommés
volumes:
data-volume:
# Réseaux personnalisés
networks:
frontend:
backend:
Exemple complet
version: "3.9"
services:
# Application web
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
- redis
networks:
- frontend
- backend
# Base de données
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
# Cache Redis
redis:
image: redis:7-alpine
networks:
- backend
volumes:
db-data:
networks:
frontend:
backend:
3 - Configuration des services
Image vs Build
services:
# Utiliser une image existante
nginx:
image: nginx:1.25-alpine
# Construire depuis un Dockerfile
app:
build: .
# Build avec options
api:
build:
context: ./api
dockerfile: Dockerfile.prod
args:
- NODE_ENV=production
Ports
services:
web:
ports:
# Format court
- "3000:3000"
- "8080:80"
# Format long
- target: 80
published: 8080
protocol: tcp
mode: host
Variables d'environnement
services:
app:
# Liste
environment:
- NODE_ENV=production
- DEBUG=false
# Map
environment:
NODE_ENV: production
DEBUG: "false"
# Fichier externe
env_file:
- .env
- .env.production
Volumes
services:
app:
volumes:
# Volume nommé
- data:/app/data
# Bind mount
- ./src:/app/src
# Lecture seule
- ./config:/app/config:ro
volumes:
data:
Réseaux
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:
internal: true # Pas d'accès externe
4 - Dépendances entre services
depends_on simple
services:
web:
depends_on:
- db
- redis
db:
image: postgres:15
redis:
image: redis:7
depends_on avec conditions
services:
web:
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
Healthcheck
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
5 - Commandes Docker Compose
Commandes principales
# Démarrer les services
docker compose up
# Démarrer en arrière-plan
docker compose up -d
# Construire et démarrer
docker compose up --build
# Arrêter les services
docker compose down
# Arrêter et supprimer les volumes
docker compose down -v
# Arrêter et supprimer les images
docker compose down --rmi all
Gestion des services
# Lister les services
docker compose ps
# Voir les logs
docker compose logs
docker compose logs -f # Suivre
docker compose logs web # Un service spécifique
# Exécuter une commande
docker compose exec web bash
docker compose exec db psql -U postgres
# Redémarrer un service
docker compose restart web
# Scaler un service
docker compose up -d --scale web=3
Build et images
# Construire les images
docker compose build
# Construire sans cache
docker compose build --no-cache
# Pousser les images
docker compose push
# Tirer les images
docker compose pull
6 - Variables et interpolation
Fichier .env
# .env
POSTGRES_VERSION=15
POSTGRES_PASSWORD=secret123
APP_PORT=3000
# docker-compose.yml
services:
db:
image: postgres:${POSTGRES_VERSION}
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
web:
ports:
- "${APP_PORT}:3000"
Valeurs par défaut
services:
web:
image: myapp:${VERSION:-latest}
environment:
LOG_LEVEL: ${LOG_LEVEL:-info}
Variables d'environnement système
# Exporter une variable
export COMPOSE_PROJECT_NAME=myproject
# Utiliser dans le compose
docker compose up
7 - Fichiers multiples et profiles
Fichiers multiples
# Fichier de base + override
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
# docker-compose.yml (base)
services:
web:
build: .
ports:
- "3000:3000"
# docker-compose.prod.yml (override)
services:
web:
image: myapp:v1.0
environment:
- NODE_ENV=production
Profiles
services:
web:
image: myapp
db:
image: postgres:15
# Service de debug, seulement quand demandé
debug:
image: nicolaka/netshoot
profiles:
- debug
# Tests, seulement quand demandé
test:
build: .
command: npm test
profiles:
- test
# Démarrer sans les profils optionnels
docker compose up
# Démarrer avec le profil debug
docker compose --profile debug up
# Plusieurs profils
docker compose --profile debug --profile test up
8 - Exemples pratiques
Stack LAMP
version: "3.9"
services:
web:
image: php:8.2-apache
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
depends_on:
- db
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: app
volumes:
- mysql-data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin:5
ports:
- "8081:80"
environment:
PMA_HOST: db
volumes:
mysql-data:
Application Node.js + MongoDB
version: "3.9"
services:
app:
build: .
ports:
- "3000:3000"
environment:
MONGODB_URI: mongodb://mongo:27017/myapp
REDIS_URL: redis://redis:6379
depends_on:
- mongo
- redis
mongo:
image: mongo:7
volumes:
- mongo-data:/data/db
redis:
image: redis:7-alpine
mongo-express:
image: mongo-express
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_SERVER: mongo
volumes:
mongo-data:
WordPress
version: "3.9"
services:
wordpress:
image: wordpress:6
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress-data:/var/www/html
depends_on:
- db
db:
image: mysql:8
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: root
volumes:
- db-data:/var/lib/mysql
volumes:
wordpress-data:
db-data:
9 - Bonnes pratiques
Organisation des fichiers
project/
├── docker-compose.yml # Base
├── docker-compose.override.yml # Dev (auto-chargé)
├── docker-compose.prod.yml # Production
├── .env # Variables par défaut
├── .env.production # Variables production
└── services/
├── web/
│ └── Dockerfile
└── api/
└── Dockerfile
Utiliser des versions d'images fixes
# ❌ Mauvais
services:
db:
image: postgres # ou postgres:latest
# ✅ Bon
services:
db:
image: postgres:15.4-alpine
Limiter les ressources
services:
web:
image: myapp
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
Sécurité
services:
web:
# Ne pas exécuter en root
user: "1000:1000"
# Mode lecture seule
read_only: true
# Monter tmpfs pour les fichiers temporaires
tmpfs:
- /tmp
- /var/run
Résumé des commandes
| Commande | Description |
|---|---|
docker compose up | Démarrer les services |
docker compose up -d | Démarrer en arrière-plan |
docker compose down | Arrêter et supprimer |
docker compose ps | Lister les services |
docker compose logs | Voir les logs |
docker compose exec | Exécuter une commande |
docker compose build | Construire les images |
docker compose pull | Télécharger les images |
docker compose restart | Redémarrer |
Points clés
- Un fichier YAML = une application complète
- Les services communiquent par leur nom
- Utilisez
depends_onavec healthcheck - Séparez la configuration dev/prod avec des fichiers multiples
Exercices pratiques
- Créez un docker-compose.yml pour une app web + base de données
- Ajoutez un service de cache Redis
- Configurez des healthchecks pour tous les services
- Créez des fichiers séparés pour dev et production