Skip to content
Learni
Voir tous les tutoriels
DevOps

Comment orchestrer des conteneurs avec Docker Compose en 2026

Read in English

Introduction

Docker Compose est un outil essentiel pour orchestrer plusieurs conteneurs Docker en une seule commande, idéal pour les environnements de développement et de test complexes. Contrairement à docker run manuel, il gère les dépendances, les volumes persistants, les réseaux isolés et le scaling via un fichier YAML déclaratif.

Pourquoi l'utiliser en 2026 ? Les applications modernes sont multi-conteneurs : une API Node.js backend, une base PostgreSQL, un cache Redis. Docker Compose reproduit fidèlement ces stacks localement, accélérant le onboarding des devs et évitant les 'ça marche sur ma machine'. Ce tutoriel intermédiaire vous guide pour créer une stack complète : un serveur Express connecté à Postgres et Redis, avec persistance des données et exposition sécurisée.

À la fin, vous maîtriserez les volumes, networks, depends_on et overrides pour des environnements prod-like. Temps estimé : 20 min pour un setup fonctionnel.

Prérequis

  • Docker Desktop installé (version 27+ avec Compose v2 intégré)
  • Connaissances de base en Docker (images, conteneurs)
  • Node.js 20+ localement pour tester l'app
  • Éditeur de code (VS Code recommandé avec extension Docker)
  • Terminal Unix-like (WSL2 sur Windows)

Créer le Dockerfile de l'application Node.js

Dockerfile
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]
USER node

Ce Dockerfile multi-étapes minimise l'image finale (Alpine pour légèreté). Il copie d'abord package.json pour optimiser le cache Docker, installe les deps en prod, puis l'app. L'utilisateur 'node' renforce la sécurité en évitant root. Copiez-collez dans un dossier projet.

Préparer l'application Node.js

Créez un dossier projet (mkdir ma-stack && cd ma-stack). Ajoutez un serveur Express simple qui interagit avec Postgres et Redis. Ce code illustre les connexions : requête DB et cache Redis. Les variables d'env seront injectées par Compose.

Implémenter le serveur Express

server.js
const express = require('express');
const { Pool } = require('pg');
const redis = require('redis');

const app = express();
app.use(express.json());

// Connexions via env vars de Compose
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const client = redis.createClient({ url: process.env.REDIS_URL });
client.connect();

app.get('/users', async (req, res) => {
  const cached = await client.get('users');
  if (cached) return res.json(JSON.parse(cached));

  const { rows } = await pool.query('SELECT * FROM users');
  await client.set('users', JSON.stringify(rows), { EX: 60 });
  res.json(rows);
});

app.listen(3000, () => console.log('Server on 3000'));

module.exports = app;

Ce serveur expose /users : vérifie le cache Redis, sinon query Postgres et cache 60s. Utilise process.env pour les URLs DB/Redis fournies par Compose. Ajoutez npm init -y && npm i express pg redis localement pour tester.

Générer package.json

package.json
{
  "name": "docker-compose-app",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.19.2",
    "pg": "^8.13.0",
    "redis": "^4.7.0"
  }
}

Package.json minimal pour prod : deps only, no devDeps. Le script start match le CMD du Dockerfile. Exécutez npm install une fois pour générer node_modules, mais Docker le rebuildera.

Définir la stack de base avec docker-compose.yml

Maintenant, orchestrez tout : web (Node), db (Postgres), redis. Exposez les ports, mappez volumes pour persistance DB, définissez un réseau interne. depends_on assure le démarrage ordonné.

Fichier docker-compose.yml de base

docker-compose.yml
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    networks:
      - app-network

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    networks:
      - app-network

volumes:
  postgres_data:

networks:
  app-network:
    driver: bridge

YAML déclaratif : build: . pour Dockerfile local, env vars partagées via noms services (db → postgres@db). Volume named persiste DB. Réseau 'app-network' isole le trafic. Lancez avec docker compose up -d.

Initialiser la base de données

Attention : Postgres démarre vide. Ajoutez un script d'init pour créer la table users. Utilisez un volume pour un fichier SQL monté.

Script d'initialisation SQL

init.sql
CREATE TABLE IF NOT EXISTS users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100),
  email VARCHAR(100) UNIQUE
);

INSERT INTO users (name, email) VALUES
  ('Alice', 'alice@example.com'),
  ('Bob', 'bob@example.com')
ON CONFLICT (email) DO NOTHING;

Ce script crée la table et insère des données de test. Montez-le dans /docker-entrypoint-initdb.d/ de Postgres pour auto-exécution au premier démarrage.

docker-compose.yml mis à jour avec init DB

docker-compose.yml
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/mydb
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    networks:
      - app-network

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    networks:
      - app-network

volumes:
  postgres_data:

networks:
  app-network:
    driver: bridge

Ajout du volume ./init.sql : Postgres l'exécute automatiquement. Parfait pour seeds. Testez : docker compose up -d && curl http://localhost:3000/users.

Commandes essentielles pour gérer la stack

Utilisez docker compose (v2) : up -d pour detached, logs -f pour suivre, down -v pour nettoyer volumes.

Script bash de gestion

manage.sh
#!/bin/bash
case $1 in
  up)
    docker compose up -d
    ;;
  down)
    docker compose down -v
    ;;
  logs)
    docker compose logs -f web
    ;;
  test)
    curl http://localhost:3000/users || echo "Erreur"
    ;;
  *)
    echo "Usage: ./manage.sh {up|down|logs|test}"
    ;;
esac

Script wrapper pour workflows : chmod +x manage.sh && ./manage.sh up. Simplifie les ops quotidiennes. Ajoutez à votre projet.

Bonnes pratiques

  • Utilisez des .env files : cp .env.example .env pour secrets (DB_PASS=xxx), référencez avec ${DB_PASS} dans YAML.
  • Networks et depends_on conditionnels : Ajoutez condition: service_healthy pour healthchecks.
  • Volumes named : Toujours pour persistance, bind mounts pour dev (hot-reload).
  • Compose overrides : docker-compose.override.yml pour dev vs prod diffs.
  • Scaling : docker compose up --scale web=3 pour tester haute dispo.

Erreurs courantes à éviter

  • depends_on sans healthcheck : DB 'ready' ≠ 'healthy'. Ajoutez healthcheck dans service db.
  • Ports exposés publiquement : Utilisez ports: - "127.0.0.1:3000:3000" pour localhost only.
  • Volumes non persistants : Oubli → perte données à down. Toujours named volumes.
  • Mauvaises images : Préférez -alpine pour taille/security, pinned tags (postgres:16-alpine).

Pour aller plus loin

Passez à Kubernetes avec Kompose (kompose convert), ou explorez Docker Swarm pour prod. Lisez la doc officielle Docker Compose. Découvrez nos formations Learni sur DevOps et Containerisation pour maîtriser Helm, Terraform et CI/CD.