Aller au contenu principal

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

CommandeDescription
docker compose upDémarrer les services
docker compose up -dDémarrer en arrière-plan
docker compose downArrêter et supprimer
docker compose psLister les services
docker compose logsVoir les logs
docker compose execExécuter une commande
docker compose buildConstruire les images
docker compose pullTélécharger les images
docker compose restartRedémarrer
Points clés
  • Un fichier YAML = une application complète
  • Les services communiquent par leur nom
  • Utilisez depends_on avec healthcheck
  • Séparez la configuration dev/prod avec des fichiers multiples

Exercices pratiques

  1. Créez un docker-compose.yml pour une app web + base de données
  2. Ajoutez un service de cache Redis
  3. Configurez des healthchecks pour tous les services
  4. Créez des fichiers séparés pour dev et production

← Réseaux Docker | Bonnes pratiques →