Introduction
Un environnement local proche de la production se rentabilise rapidement. Lorsque votre application, la base de données, le cache et le proxy tournent ensemble sous Docker Compose avec des réglages réalistes, vous détectez les problèmes d'intégration plus tôt, déboguez plus vite et réduisez les surprises en staging et en production. Ce guide montre comment bâtir cette configuration avec des services, des réseaux, des volumes, des fichiers d'environnement, des vérifications de santé et un workflow de débogage pratique.
Aperçu du workflow
Utilisez une boucle simple qui reflète la manière dont le logiciel est livré :
- Planifier
- Lister les services et leurs communications (ports, protocoles, variables d'environnement).
- Décider des réseaux, volumes et critères de santé pour chaque service.
- Construire
- Créer des Dockerfiles proches de la production (images légères, utilisateur non-root, versions épinglées).
- Utiliser
docker buildou laisser Compose builder à partir de votre Dockerfile.
- Exécuter
- Démarrer la pile avec
docker compose up -d. - Attendre que les health checks deviennent « healthy ».
- Tester
- Envoyer du trafic par le point d'entrée public (par exemple Nginx sur le port 80).
- Valider la disponibilité (readiness), la vivacité (liveness) et les cas d'usage principaux.
- Itérer
- Modifier configs ou code, reconstruire et relancer.
Cette séparation claire des étapes aide à garder les changements compréhensibles et réduit le retravail.
Conception du fichier Compose
Voici un docker-compose.yml pratique pour une petite pile web : une application Node.js, Postgres, Redis et Nginx comme proxy d'entrée. Il utilise deux réseaux (frontend et backend), des volumes nommés pour les données, des fichiers d'environnement pour la configuration et des health checks avec ordonnancement au démarrage.
version: '3.9'
services:
web:
build:
context: ./web
image: local/web:dev
ports:
- '8080:3000'
env_file:
- ./env/web.env
environment:
- NODE_ENV=development
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ['CMD-SHELL', 'wget -qO- http://localhost:3000/health || exit 1']
interval: 10s
timeout: 3s
retries: 5
start_period: 15s
volumes:
- ./web:/app:cached
- web-node-modules:/app/node_modules
networks:
- frontend
- backend
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: appdb
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U app -d appdb']
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
redis:
image: redis:7-alpine
command: ['redis-server', '--appendonly', 'yes']
volumes:
- redis-data:/data
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 3s
retries: 5
networks:
- backend
nginx:
image: nginx:1.25-alpine
depends_on:
web:
condition: service_healthy
ports:
- '80:80'
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
networks:
- frontend
volumes:
db-data:
redis-data:
web-node-modules:
networks:
frontend:
backend:
Exemple de configuration Nginx
Achemine le trafic du port 80 vers le service web.
# ./nginx/conf.d/app.conf
server {
listen 80;
server_name _;
location / {
proxy_pass http://web:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /healthz {
return 200 'ok';
add_header Content-Type text/plain;
}
}
Exemple de Dockerfile Node.js
Restez proche de la production : base minimale, utilisateur non-root, version épinglée et un endpoint de santé simple dans votre application à /health.
# ./web/Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN addgroup -S app && adduser -S app -G app && chown -R app:app /app
USER app
EXPOSE 3000
CMD node server.js
Exemple d'application Node minimale
// ./web/server.js
const express = require('express');
const app = express();
const port = 3000;
app.get('/health', (req, res) => res.send('ok'));
app.get('/', (req, res) => res.send('Hello from web via Nginx'));
app.listen(port, () => console.log(`web listening on ${port}`));
Variables d'environnement et secrets
Utilisez un fichier .env au niveau du projet pour les variables de Compose, et des fichiers d'environnement par service pour les réglages de l'application.
- Le
.envdu projet contrôle le comportement de Compose et les valeurs partagées. - Les fichiers d'environnement des services contrôlent les paramètres applicatifs.
- Ne commettez pas de vrais secrets. Fournissez des fichiers d'exemple et chargez les valeurs réelles depuis un emplacement sécurisé.
Exemple de .env du projet :
# ./.env
COMPOSE_PROJECT_NAME=prodlike
WEB_PORT=8080
Exemple de fichier d'environnement de service :
# ./env/web.env
PORT=3000
DATABASE_URL=postgresql://app:app@db:5432/appdb
REDIS_URL=redis://redis:6379/0
Vous pouvez référencer ${WEB_PORT} dans votre fichier compose si vous préférez éviter les ports en dur.
Vérifications de santé et ordre de démarrage
Les health checks rendent la disponibilité des dépendances explicite. Utilisez healthcheck dans chaque service et depends_on avec condition: service_healthy dans les services dépendants. Cela empêche le service web de démarrer avant que la base de données ne soit prête.
- Santé du web :
GET /healthrenvoie 200. - Santé de Postgres :
pg_isreadyréussit. - Santé de Redis :
redis-cli pingrenvoie PONG.
Compose affiche l'état de santé dans docker compose ps pour savoir quand la pile est prête.
Démarrage, test et itération
Démarrez la pile :
docker compose up -d --build
Vérifiez l'état et la santé :
docker compose ps
docker compose logs -f --tail=100 web db redis nginx
Testez via le proxy comme un utilisateur :
curl -sS http://localhost/
Options de rechargement à chaud :
- Monter
./weben bind-mount dans le conteneur pour des éditions locales rapides. - Si vous avez besoin de nodemon, ajoutez-le dans
devDependencieset lancez-le via un fichier compose d'override réservé au développement local.
Reconstruisez quand le Dockerfile change :
docker compose build web && docker compose up -d web
Débogage et résolution de problèmes
Vérifications et correctifs courants :
- Conflits de ports
- Symptôme :
docker compose upn'arrive pas à exposer un port. - Correctif : changer les ports hôtes (ex.
WEB_PORT), ou arrêter le processus en conflit.
- Health check qui échoue en boucle
- Consulter les logs du conteneur :
docker compose logs web. - Entrer dans le conteneur et appeler l'endpoint de santé localement :
docker compose exec web sh -lc 'wget -qO- http://localhost:3000/health'. - Vérifier que les variables d'environnement sont définies :
docker compose exec web env | sort.
- L'application ne rejoint pas la base de données ou Redis
- Vérifier la résolution DNS dans le réseau :
docker compose exec web getent hosts db redis. - Tester la connectivité TCP :
docker compose exec web sh -lc 'nc -zv db 5432'etnc -zv redis 6379.
- Permissions de volume sous Linux
- Symptôme :
EACCESà l'écriture. - Correctif : aligner l'UID/GID du conteneur sur celui de l'utilisateur hôte, ou
chownle répertoire de travail pendant le build comme montré dans le Dockerfile.
- Synchronisation de fichiers lente sur macOS/Windows
- Symptôme : rechargement à chaud lent.
- Correctif : utiliser l'option
:cached, déplacer les dépendances lourdes vers un volume nommé (web-node-modules), ou reconstruire les images plus souvent au lieu de tout monter en live.
- Données réinitialisées de façon inattendue
- S'assurer d'utiliser des volumes nommés (
db-data,redis-data) plutôt que des volumes anonymes. docker compose down -vsupprime les volumes nommés ; à utiliser avec précaution.
- Environnement non appliqué
- Vérifier l'ordre de résolution :
.env, shell,env_file. - Afficher la config finale :
docker compose config.
Commandes utiles :
docker compose config
docker compose ps --format json | jq '.'
docker compose logs -f web
docker compose exec -it web sh
docker compose inspect web
# Réseaux et volumes
docker network ls
docker network inspect prodlike_backend
docker volume ls
Plan pilote local
Commencez petit, mesurez, puis élargissez.
Périmètre
- Services : web + db uniquement.
- Critères de succès :
- Temps entre
docker compose up -det les deux services « healthy » < 15 secondes sur votre machine. curl http://localhost/renvoie 200 et le contenu attendu.docker compose restart webrevient à « healthy » en < 5 secondes.
Étapes
- Implémenter les endpoints de santé et les checks pour web et db.
- Ajouter un volume nommé pour les données Postgres.
- Brancher l'environnement via
./env/web.envet./.env. - Mesurer les temps de référence avec les commandes de ce guide.
- Ajouter Redis et Nginx quand le pilote atteint les critères de succès.
Pourquoi ça fonctionne
- Un périmètre étroit est plus simple à déboguer et à comprendre.
- Des résultats clairs et mesurables indiquent quand faire grandir la pile.
Conclusion
Une configuration Docker Compose proche de la production vous donne un retour rapide et réaliste sans quitter votre poste de travail. Modélisez votre pile avec des services, réseaux et volumes ; configurez via des fichiers d'environnement ; et utilisez des health checks ainsi qu'un workflow reproductible pour réduire le retravail. Lancez un pilote étroit, mesurez les résultats, puis étendez vers une parité complète.