E-NO
DevOps 8 min de lecture

Optimisation des performances Docker Compose avec des exemples pratiques : guide d'implémentation

calendar_today Publié : 2026-07-27
update Dernière mise à jour : 2026-07-27
analytics Efficacité SEO : 97%
Illustration du guide technique pour « Optimisation des performances Docker Compose avec des exemples pratiques : guide d'implémentation ».

Introduction

Compose simplifie la vie des équipes multi‑services, mais il est facile de livrer une pile lente si l'on accepte tous les réglages par défaut. Les goulets d'étranglement fréquents sont bien connus :

  • I/O fichier : les bind mounts sur macOS et Windows sont bien plus lents que les volumes natifs Linux. Les bases de données en souffrent particulièrement.
  • CPU et mémoire : des limites trop basses ou des voisins bruyants provoquent du throttling et du swap.
  • Réseau : des sauts supplémentaires et le NAT ajoutent de la latence ; les résolutions DNS et des health checks trop bavards chargent la pile.
  • Logs : des journaux non bornés grossissent et volent de l'I/O au travail utile.
  • Conteneurs très écrits : caches et répertoires temporaires dégradent le débit s'ils ne sont pas déplacés en tmpfs.

Ce guide montre un chemin sûr, par étapes, pour trouver les goulots d'étranglement, dimensionner correctement les ressources et régler la latence comme le débit. Vous verrez des extraits Compose concrets pour Nginx, PostgreSQL et Redis, ainsi que des vérifications rapides à exécuter en local avant tout changement dans des environnements partagés. L'objectif est une optimisation des performances Docker Compose pragmatique et mesurable.

Vue d'ensemble du workflow

Adoptez un flux court et reproductible afin que chaque amélioration soit évidente et sûre.

  1. Définir les objectifs
  • SLO de latence : p50, p95, p99 pour vos endpoints et commandes clés.
  • Cibles de débit : requêtes/s, TPS, ops/sec.
  • Plafonds de ressources : CPU et mémoire max par service.
  1. Établir une baseline rapide
  • Démarrez la pile et attendez l'état « healthy ».
  • Enregistrez un cliché de 1-2 minutes CPU/Mémoire/I/O avec docker stats.
  • Mesurez la latence HTTP :
  • curl -s -o /dev/null -w "time_connect=%{time_connect} time_starttransfer=%{time_starttransfer} time_total=%{time_total}\n" http://localhost:8080/
  • Mesurez des opérations simples DB/cache : un SELECT trivial dans PostgreSQL et un GET/SET dans Redis.
  1. Identifier les contraintes
  • Points chauds I/O : services avec écritures élevées sur bind mounts.
  • Saturation CPU : conteneurs proches de 100 % d'un cœur ou souvent throttlés.
  • Pression mémoire : OOM kills, reclaim élevé ; buffers partagés DB trop petits.
  • Réseau : temps de connexion lents, délais DNS, backlog SYN élevé.
  • Logs : débit de logs élevé ou fichiers volumineux.
  1. Appliquer un seul changement à la fois
  • Préférez les volumes nommés pour les bases. Gardez les bind mounts avec cached/delegated pour le code/config à éditer à chaud.
  • Ajoutez du tmpfs pour les caches et répertoires temporaires chauds.
  • Fixez des limites CPU/mémoire conservatrices, puis augmentez progressivement.
  • Bornage et rotation des logs avec le driver local.
  • Ajustez les health checks pour réduire le bruit sans sacrifier la sécurité.
  1. Re‑tester et comparer
  • Rejouez les mêmes commandes curl et charges. Conservez fenêtre, concurrence et dataset identiques.
  • Si les chiffres s'améliorent sans hausse d'erreurs, gardez le changement ; sinon, revenez en arrière.

Plan pilote local

Commencez par un pilote restreint facile à inspecter en local. L'exemple ci‑dessous s'appuie sur Nginx, PostgreSQL et Redis, et cible l'I/O fichier, les plafonds de ressources, la journalisation et les health checks. Adaptez l'upstream web et les identifiants DB à votre pile.

Baseline compose.yml

version: "3.9"

services:
  web:
    image: nginx:1.25-alpine
    ports:
      - "8080:80"
    volumes:
      # Config en bind mount en lecture seule pour la commodité
      - ./nginx.conf:/etc/nginx/nginx.conf: ro
      # Cache sur volume nommé pour éviter la lenteur des bind mounts
      - nginx_cache:/var/cache/nginx
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost"]
      interval: 10s
      timeout: 2s
      retries: 3
    # Journaux bornés et légers
    logging:
      driver: local
      options:
        max-size: "10m"
        max-file: "3"
    # Limites conservatrices (prises en charge par docker compose sous Linux)
    cpus: "1.5"
    mem_limit: "512m"
    # Plus de descripteurs pour des tests à haute connexion
    ulimits:
      nofile: 65536
    # Réduit les pertes de file d'attente sous charge
    sysctls:
      net.core.somaxconn: "65535"

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: example
      POSTGRES_DB: app
      POSTGRES_USER: app
    # Volume nommé pour le stockage durable (plus rapide que bind mount sur macOS/Windows)
    volumes:
      - pgdata:/var/lib/postgresql/data
    # Plus de mémoire partagée pour réduire la contention IPC
    shm_size: "512m"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 10s
      timeout: 3s
      retries: 5
    logging:
      driver: local
      options:
        max-size: "10m"
        max-file: "3"
    cpus: "2"
    mem_limit: "1g"

  cache:
    image: redis:7-alpine
    command: [
      "redis-server",
      "--appendonly", "no",
      "--maxmemory", "256mb",
      "--maxmemory-policy", "allkeys-lru"
    ]
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 2s
      retries: 5
    logging:
      driver: local
      options:
        max-size: "10m"
        max-file: "3"
    cpus: "1"
    mem_limit: "384m"
    # File d'acceptation plus rapide sous charge en rafale
    sysctls:
      net.core.somaxconn: "65535"

volumes:
  pgdata: {}
  nginx_cache: {}

Notes

  • Utilisez des volumes nommés pour Postgres et le cache Nginx. Cela évite la lenteur des bind mounts sur macOS/Windows et reste performant sous Linux.
  • Laissez la config en bind mount lecture seule pour la commodité, pas pour l'I/O à haut débit.
  • Les paramètres cpus et mem_limit sont des points de départ conservateurs ; adaptez‑les à votre hôte.

Réglage optionnel des bind mounts pour macOS/Windows

Si vous devez absolument bind‑monter un chemin très écrit (déconseillé pour les bases), ajoutez des drapeaux de cohérence :

services:
  app:
    volumes:
      - ./src:/app/src: cached    # lecture majoritaire
      - ./tmp:/app/tmp: delegated # écriture majoritaire

Réseau host Linux pour des benchs

Pour des expériences de latence sous Linux, vous pouvez éviter un saut NAT en utilisant le réseau host pour l'entrée HTTP :

services:
  web:
    network_mode: host  # Linux uniquement
    ports: []           # inutile avec le réseau host

N'utilisez pas le réseau host sur macOS/Windows, et évitez‑le pour le dev général à moins d'en avoir besoin pour du benchmarking.

Ajouter du tmpfs pour les écritures chaudes

Réduisez l'I/O disque en déplaçant les répertoires temporaires/caches en RAM :

services:
  web:
    tmpfs:
      - /var/cache/nginx
  cache:
    tmpfs:
      - /tmp

Vérifications rapides de latence et de débit

Lancez‑les après que la pile soit healthy pour capturer une baseline :

  • Latence HTTP (p50 sur petit échantillon) :
  • curl -s -o /dev/null -w "time_connect=%{time_connect} time_starttransfer=%{time_starttransfer} time_total=%{time_total}\n" http://localhost:8080/
  • Débit HTTP (si vous avez hey) :
  • hey -z 30s -c 50 http://localhost:8080/
  • Vérification rapide PostgreSQL :
  • psql "postgresql://app: example@localhost:5432/app" -c "select 1;"
  • Si vous avez pgbench : pgbench -S -T 30 -c 16 -j 4 "postgresql://app: example@localhost:5432/app"
  • Vérification rapide Redis :
  • redis-cli -h localhost -p 6379 ping
  • Si vous avez redis-benchmark : redis-benchmark -t get, set -n 100000 -q

Répétez exactement les mêmes commandes après chaque changement. Conservez durée, concurrence et dataset constants pour rendre les comparaisons fiables.

Recettes d'optimisation pratiques

  1. Éliminer les bind mounts lents là où ça fait mal
  • Volumes nommés pour les bases de données et caches de service.
  • Conservez code source et configs en bind mount si l'édition à chaud est utile.
  • Sur macOS/Windows, préférez :cached pour la lecture majoritaire et :delegated pour l'écriture majoritaire.
  1. Dimensionner correctement CPU et mémoire
  • Démarrez avec cpus et mem_limit conservateurs et augmentez jusqu'à disparition du throttling et stabilisation de la latence.
  • Isolez des cœurs si nécessaire pour éviter les voisins bruyants :
services:
  db:
    cpuset: "1-2"
  1. Maîtriser la surcharge de logs
  • Utilisez le driver local avec taille et rotation bornées. Évitez json-file non borné.
  1. Régler les health checks
  • Indispensables pour la dispo, mais peuvent charger la pile. Utilisez une sonde simple/rapide, un intervalle de 10-30 s, et un petit timeout.
  1. Déplacer les temporaires chauds en tmpfs
  • Idéal pour caches et fichiers éphémères qu'on peut perdre sans risque.
  1. Augmenter certaines files noyau prudemment
  • Des taux de connexions élevés bénéficient d'un somaxconn plus grand.
  1. Mesurer, ne pas deviner
  • Rejouez les mêmes tests avant/après. Prenez des notes de chaque changement et de ses résultats.

Optimisation sûre via overrides et profils

Gardez votre compose.yml de base simple. Placez les réglages de tuning dans un override pour activer à la demande :

# compose.override.yml
services:
  web:
    tmpfs:
      - /var/cache/nginx
    environment:
      NGINX_ENV: bench
  db:
    mem_limit: "2g"
  cache:
    command: [
      "redis-server",
      "--appendonly", "no",
      "--save", "",
      "--maxmemory", "512mb",
      "--maxmemory-policy", "allkeys-lru"
    ]

Ou utilisez des profils pour des réglages réservés aux benchs :

services:
  web:
    profiles: ["bench"]
    network_mode: host  # Linux uniquement
    ports: []

Activation :

  • COMPOSE_PROFILES=bench docker compose up -d

Checklist de dépannage

  • Pics de latence après quelques minutes : vérifiez les logs (rotation), augmentez le tmpfs des caches, confirmez l'absence d'OOM kills.
  • Écritures lentes Postgres : assurez‑vous que les données sont sur un volume nommé, augmentez shm_size, gardez le WAL sur le même volume nommé.
  • Timeouts Redis sous rafale : augmentez somaxconn et nofile, envisagez le réseau host sous Linux pour les tests, vérifiez la politique maxmemory.
  • Throttling CPU : augmentez cpus ou réduisez la concurrence ; vérifiez l'isolement cpuset.
  • I/O fichier macOS/Windows : remplacez les bind mounts par des volumes nommés sur les chemins chauds ; appliquez :cached/:delegated seulement en dernier recours.

Conclusion

Gardez une boucle serrée : définissez vos objectifs, établissez une baseline, changez un seul paramètre, remesurez et journalisez les résultats. Commencez avec des réglages sûrs, préférez les volumes nommés pour l'I/O chaud, bornez vos journaux et utilisez tmpfs pour les écritures éphémères. Une fois des gains nets observés en local, capturez‑les dans des overrides ou des profils pour une adoption d'équipe cohérente. Revalidez régulièrement vos chiffres au fil des mises à jour d'images, des versions d'OS hôte et de l'évolution des charges pour que vos stacks restent rapides et prévisibles, avec une Docker Compose latency maîtrisée et des Docker Compose bottlenecks sous contrôle.

Score de qualité de l’article

Utilité pour le lecteur 97%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO