← Retour au cours
▶ Aperçu gratuit · Leçon offerte

Leçon 2 — Docker Compose et passage en production

⏱ 50 min · 🎬 Lecon · 🏆 15 XP
🎬
Vidéo en production
Notre équipe pédagogique tourne actuellement cette leçon avec un·e formateur·rice expert·e. Le contenu textuel ci-dessous est complet et utilisable dès maintenant.

Leçon 2 — Docker Compose & production

Orchestrer des applications multi-conteneurs, sécuriser, monitorer et préparer le passage à Kubernetes.

Objectifs pédagogiques

  • Écrire un compose.yaml production-ready (healthchecks, secrets, networks isolés)
  • Configurer logging et monitoring (json-file driver, Prometheus, cAdvisor)
  • Sécuriser un déploiement Docker (user non-root, capabilities, seccomp, image scanning Trivy)
  • Publier sur Docker Hub / GitHub Container Registry / GitLab Registry
  • Identifier les limites de Docker seul et la nécessité d'un orchestrateur K8s

Prérequis

Leçon 1 acquise (Dockerfile, volumes, réseaux). Docker Compose v2 (intégré docker compose depuis Docker 20.10+, plugin Go remplaçant docker-compose Python). Notion CI/CD (GitHub Actions, GitLab CI).

Introduction contextuelle

Docker Compose est l'outil officiel Docker pour orchestrer des applications composées de plusieurs services. Initialement écrit en Python (Fig, 2014, racheté par Docker), réécrit en Go en 2021 et intégré comme plugin CLI. Il consomme un fichier YAML déclaratif (compose.yaml ou docker-compose.yml) décrivant services, volumes, réseaux, secrets, configs.

Pour des applications jusqu'à 10-15 conteneurs sur un seul hôte, Compose suffit largement. Au-delà — multi-hôte, haute disponibilité, scaling auto, load balancing avancé — il faut un orchestrateur de classe entreprise : Kubernetes (de loin majoritaire), Nomad (HashiCorp), ou Docker Swarm (en déclin mais maintenu).

Cette leçon explore Compose en profondeur puis trace la transition vers K8s : isomorphisme service/Deployment, volume/PVC, etc.

1. Compose.yaml — anatomie d'un fichier production

name: myapp
services:
  web:
    image: ghcr.io/acme/web:1.4.2
    restart: unless-stopped
    ports:
      - "8080:80"
    environment:
      LOG_LEVEL: info
    depends_on:
      api:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-q", "-O-", "http://localhost/health"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 10s
    deploy:
      resources:
        limits: { cpus: '1.0', memory: 512M }
        reservations: { cpus: '0.25', memory: 128M }
    logging:
      driver: json-file
      options:
        max-size: 10m
        max-file: '3'
    networks: [frontend]

  api:
    image: ghcr.io/acme/api:1.4.2
    secrets: [db_password, jwt_secret]
    networks: [frontend, backend]
    depends_on:
      db: { condition: service_healthy }
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 10s

  db:
    image: postgres:16-alpine
    volumes: [pgdata:/var/lib/postgresql/data]
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets: [db_password]
    networks: [backend]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 10s

volumes:
  pgdata:

networks:
  frontend: { driver: bridge }
  backend:
    driver: bridge
    internal: true   # pas d'accès Internet

secrets:
  db_password: { file: ./secrets/db_password.txt }
  jwt_secret:  { file: ./secrets/jwt_secret.txt }

Points-clés du compose ci-dessus

  • restart: unless-stopped — résilience hôte
  • depends_on.condition: service_healthy — orchestration ordonnée
  • networks: internal: true — DB sans Internet
  • secrets: — pas de mot de passe en clair dans env
  • deploy.resources.limits — limites mémoire/CPU strictes
  • logging.options.max-size — rotation logs JSON

2. Commandes Compose essentielles

  • docker compose up -d — démarrer en arrière-plan
  • docker compose ps — état
  • docker compose logs -f api — logs streaming
  • docker compose exec api sh — shell dans le service
  • docker compose pull && docker compose up -d — rolling update
  • docker compose down -v — arrêter + supprimer volumes
  • docker compose config — valider le yaml + interpolation env
  • docker compose --profile dev up — profils conditionnels

3. Sécurité Docker en production

3.1 CIS Docker Benchmark

Le Center for Internet Security publie le CIS Docker Benchmark v1.6 (2024) avec 100+ recommandations. Outil d'audit : docker run --net host --pid host --userns host --cap-add audit_control -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST -v /etc:/etc:ro -v /usr/bin/containerd:/usr/bin/containerd:ro -v /usr/bin/runc:/usr/bin/runc:ro -v /usr/lib/systemd:/usr/lib/systemd:ro -v /var/lib:/var/lib:ro -v /var/run/docker.sock:/var/run/docker.sock:ro --label docker_bench_security docker/docker-bench-security.

3.2 Image scanning

  • Trivy (Aqua Security) : trivy image my-api:v1 → CVE + secrets + misconfigs
  • Grype (Anchore) : grype my-api:v1
  • Docker Scout (intégré Desktop) : docker scout cves my-api:v1
  • Snyk Container, Clair (Quay)

3.3 Bonnes pratiques runtime

  • --read-only : système de fichiers en lecture seule
  • --cap-drop ALL --cap-add NET_BIND_SERVICE : capabilities minimales
  • --security-opt no-new-privileges : empêche setuid
  • --user 1000:1000 : forcer utilisateur non-root
  • --pids-limit 100 : fork bomb protection
  • --cpus 1.0 --memory 512m : limites cgroup
Selon le NIST SP 800-190 (Application Container Security Guide) : « Container images should be scanned for vulnerabilities continuously, both at build time and at registry. Runtime workloads should drop unnecessary capabilities. » (NIST, 2017).

4. Publication d'images

4.1 Docker Hub

docker login
docker tag my-api:v1 acme/my-api:1.4.2
docker push acme/my-api:1.4.2
# repos privés : abonnement Docker Pro/Team

4.2 GitHub Container Registry (ghcr.io)

echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
docker tag my-api:v1 ghcr.io/USERNAME/my-api:1.4.2
docker push ghcr.io/USERNAME/my-api:1.4.2

4.3 Image signing (cosign — Sigstore)

Sigstore cosign (CNCF, 2021) permet de signer cryptographiquement les images : cosign sign --key cosign.key acme/my-api:1.4.2, vérification cosign verify --key cosign.pub acme/my-api:1.4.2. Indispensable supply-chain SLSA Level 2+.

5. Monitoring et logging

  • cAdvisor (Google) : métriques par conteneur (CPU, RAM, IO, réseau)
  • Prometheus + Grafana : stack monitoring de référence
  • Loki + Promtail (Grafana Labs) : agrégation logs
  • Fluent Bit / Fluentd : forwarders performants
  • OpenTelemetry : observabilité unifiée (logs, metrics, traces)

Cas pratique — Stack LAMP en production (Compose)

  1. Créer projet my-shop/ avec arborescence : api/, web/, secrets/, compose.yaml
  2. Écrire compose.yaml avec : nginx (web), php-fpm (api), mariadb (db), networks isolés
  3. Ajouter healthchecks chacun
  4. Scanner les images : trivy image nginx:1.27-alpine
  5. Démarrer : docker compose up -d
  6. Vérifier : curl -i http://localhost
  7. Logs : docker compose logs -f --tail 50
  8. Push images vers ghcr.io
  9. Signer cosign + vérifier

Livrable : compose.yaml versionné Git, scan Trivy 0 critique, image signée cosign.

6. Limites de Docker seul → vers Kubernetes

BesoinDocker seulKubernetes
Multi-hôteCompose monolithe / SwarmNative, des dizaines/centaines de nodes
Auto-scalingManuelHPA / VPA / Cluster Autoscaler
Self-healingrestart: unless-stoppedReplicaSet + liveness/readiness
Load balancingnginx customService + Ingress + IngressClass
Rolling updatesManuelStrategy: RollingUpdate
Service discoveryDNS DockerCoreDNS K8s
StorageVolumes locauxStorageClass + PV/PVC + CSI
Network policiesLimité bridgeNetworkPolicy + CNI (Calico, Cilium)
Écosystème~50 outilsCNCF Landscape 1500+ projets
Pièges fréquents Compose :
  • Versions YAML : version top-level déprécié depuis Compose v2 → utiliser name
  • depends_on n'attend que le démarrage (pas la santé) sans condition!
  • Bind mount ./ → owner uid/gid host vs container → erreurs permissions
  • Pas de built-in HA — restart sur même hôte uniquement
  • Secrets Compose != Docker secrets Swarm
  • Pas de network policies (filtrage L3/L4 inter-services)

Synthèse — points-clés à retenir

  • compose.yaml = manifest déclaratif multi-services
  • Healthchecks + depends_on condition = ordre fiable
  • Secrets file plutôt qu'env vars en clair
  • Networks séparés frontend/backend + internal=true
  • Trivy / Grype / Scout = scanning images obligatoire
  • Cosign / Sigstore = signature images SLSA
  • cAdvisor + Prometheus + Grafana = observabilité standard
  • Compose plafonne à 1 hôte → K8s obligatoire pour scale-out

Pour aller plus loin

Continuez le parcours 🚀

Inscrivez-vous pour accéder aux 5 autres leçons + le quiz final.

Créer mon compte
🍪 Nous utilisons des cookies essentiels et, avec ton accord, des cookies analytiques. En savoir plus

⚙️ Préférences cookies

Choisis quels cookies tu acceptes — modifiable à tout moment.

🔐 Essentiels (obligatoires)Authentification, session, sécurité. Toujours actifs.
📊 Analytics anonymesMesure d'audience anonymisée — aucune donnée personnelle.
📣 MarketingPublicités ITAG pertinentes sur d'autres sites.
💬 Contactez-nous sur WhatsApp