E-NO
DevOps 8 min de lecture

Optimisation des performances de Docker Compose : guide pratique avec exemples

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 de Docker Compose : guide pratique avec exemples ».

Introduction

Docker Compose simplifie le développement et l’exploitation multi‑services, mais il est facile de livrer une pile lente si l’on conserve tous les paramètres par défaut. Les goulots d’étranglement les plus fréquents sont :

  • E/S fichiers : les montages bind sur macOS et Windows peuvent être 5 à 10 fois plus lents que les volumes natifs Linux. Les bases de données en souffrent le plus.
  • CPU et mémoire : des limites trop basses ou des voisins bruyants provoquent du throttling et du swapping.
  • Réseau : sauts supplémentaires et NAT ajoutent de la latence ; les recherches DNS et les health‑checks bavards augmentent la charge.
  • Journalisation : des logs non bornés grossissent et volent de l’I/O au travail réel.
  • Conteneurs qui écrivent massivement sur disque : caches et fichiers temporaires dégradent le débit s’ils ne sont pas déplacés vers tmpfs.

Ce guide présente une méthode sûre, par étapes, pour identifier les goulots, dimensionner les ressources et optimiser la latence comme le débit. Vous y trouverez des extraits Compose concrets pour NGINX, PostgreSQL et Redis, ainsi que des vérifications rapides à exécuter localement avant toute modification dans des environnements partagés.

Vue d’ensemble du flux de travail

Utilisez un flux court et reproductible pour que les améliorations soient évidentes et sans risque.

1. Définir les objectifs

  • SLO de latence : p50, p95, p99 pour vos points de terminaison et commandes clés.
  • Cibles de débit : requêtes par seconde, TPS, ops/sec.
  • Plafonds de ressources : CPU et mémoire maximum par service.

2. Établir une ligne de base rapidement

  1. Démarrez la pile et attendez qu’elle soit saine.
  2. Enregistrez un instantané de 1 à 2 minutes de CPU, mémoire et I/O avec docker stats.
  3. 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/
  1. Mesurez des opérations simples de base de données et de cache : lancez un SELECT trivial dans PostgreSQL et un GET/SET dans Redis.

3. Identifier les contraintes

  • Points chauds d’E/S fichiers : bases de données ou services à fort taux d’écriture sur montages bind.
  • Saturation CPU : conteneurs près de 100 % d’un cœur ou souvent throttlés.
  • Pression mémoire : OOM kills ou récupération intensive ; shared_buffers de la base trop petit.
  • Problèmes réseau : temps de connexion lents, retards DNS, ou backlog SYN élevé.
  • Journalisation : débit de logs élevé ou fichiers volumineux.

4. Appliquer un changement à la fois

  • Privilégiez les volumes nommés pour les bases de données. Utilisez les montages bind avec cached/delegated uniquement pour le code source ou les configurations qui profitent de l’édition en direct.
  • Ajoutez tmpfs pour les caches chauds et les répertoires temporaires.
  • Définissez des limites CPU et mémoire conservatrices, puis augmentez progressivement.
  • Bornez et compactez les logs avec le driver local.
  • Ajustez les intervalles des health‑checks pour réduire le bruit sans sacrifier la sécurité.

5. Re‑tester et comparer

Répétez les mêmes vérifications curl et de charge. Conservez la même fenêtre de temps, la même concurrence et le même jeu de données que pour la ligne de base. Si les chiffres s’améliorent et que les taux d’erreur restent stables, conservez le changement. Sinon, revenez en arrière.

Question rapide 1 sur 2

Selon le passage, quelle fonctionnalité de Docker Desktop peut réduire considérablement le temps de synchronisation entre l'hôte et la VM sur macOS, entraînant des améliorations substantielles des performances ?

Le passage indique que VirtioFS a démontré une réduction drastique du temps nécessaire pour synchroniser les modifications entre l'hôte et la VM, ce qui entraîne des améliorations substantielles des performances.

Plan pilote local

Commencez par un pilote étroit, facile à inspecter en local. L’exemple ci‑dessous utilise NGINX, PostgreSQL et Redis. Il se concentre sur l’E/S fichiers, les plafonds de ressources, la journalisation et les health‑checks. Remplacez l’upstream web et les identifiants de base de données pour adapter à votre pile.

compose.yml de référence

version: "3.9"

services:
  web:
    image: nginx:1.25-alpine
    ports:
      - "8080:80"
    volumes:
      # Config en montage bind read‑only pour commodité
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      # Cache dans un volume nommé pour éviter la lenteur du bind mount
      - nginx_cache:/var/cache/nginx
    healthcheck:
      test: ["CMD", "wget", "-qO-" , "http://localhost" ]
      interval: 10s
      timeout: 2s
      retries: 3
    # Logs bornés et légers
    logging:
      driver: local
      options:
        max-size: "10m"
        max-file: "3"
    # Limites de départ conservatrices (supportées par docker compose sur Linux)
    cpus: "1.5"
    mem_limit: "512m"
    # Augmenter les descripteurs de fichiers pour tests à forte concurrence
    ulimits:
      nofile: 65536
    # Réduire les pertes de file d’attente de connexion 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 stockage durable (plus rapide que bind mount sur macOS/Windows)
    volumes:
      - pgdata:/var/lib/postgresql/data
    # Augmenter la mémoire partagée pour Postgres afin de 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’attente d’acceptation plus grande sous charge burst
    sysctls:
      net.core.somaxconn: "65535"

volumes:
  pgdata: {}
  nginx_cache: {}

Notes

  • Utilisez des volumes nommés pour Postgres et le cache NGINX. Cela évite les bind mounts lents sur macOS et Windows et garde Linux rapide.
  • Conservez la configuration en montage bind read‑only pour la commodité, pas pour de l’I/O à haut débit.
  • Les réglages cpus et mem_limit sont des points de départ conservateurs. Adaptez‑les à votre hôte.

Ajustement optionnel des bind mounts pour macOS/Windows

Lorsque vous devez binder un chemin à forte écriture (déconseillé pour les bases de données), ajoutez les drapeaux de cohérence :

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

Réseau hôte Linux uniquement pour les bancs d’essai

Pour des expériences de latence sur Linux, vous pouvez éviter un saut NAT en utilisant le réseau hôte pour le point d’entrée HTTP :

services:
  web:
    network_mode: host   # Linux seulement
    ports: []            # non utilisé avec le réseau hôte

N’utilisez pas le réseau hôte sur macOS ou Windows, et évitez‑le pour le développement courant sauf besoin spécifique de benchmark.

Ajouter tmpfs pour les chemins d’écriture chauds

Réduisez l’I/O disque en déplaçant les répertoires temporaires ou de cache en RAM :

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

Vérifications rapides de latence et de débit

Exécutez après que la pile est saine pour capturer une ligne de base :

  • Latence HTTP (p50 sur un 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 hey est installé) :
  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 les mêmes commandes après chaque modification. Maintenez la durée, la concurrence et le jeu de données constants pour que les résultats soient comparables.

Actions de réglage pratiques

  1. Éliminer les bind mounts lents là où ils nuisent le plus
  • Utilisez des volumes nommés pour les bases de données et les caches de service.
  • Gardez le code source et les configs en bind mount si l’édition en direct est nécessaire.
  • Sur macOS/Windows, préférez :cached pour les montages à lecture majoritaire et :delegated pour les montages à écriture majoritaire.
  1. Dimensionner correctement CPU et mémoire
  • Partez de cpus et mem_limit conservateurs et augmentez jusqu’à ce que le throttling disparaisse et que la latence ne progresse plus.
  • Envisagez d’épingler des CPU pour isoler les voisins bruyants :
     services:
       db:
         cpuset: "1-2"
  1. Maîtriser la charge de journalisation
  • Utilisez le driver local et limitez la taille et la rotation. Évitez json-file sans bornes.
  1. Ajuster les health‑checks
  • Les health‑checks protègent la disponibilité mais peuvent générer de la charge. Utilisez une sonde simple et rapide, un intervalle de 10 à 30 s et un timeout court.
  1. Déplacer les données temporaires chaudes vers tmpfs
  • Idéal pour les caches et fichiers éphémères qu’il est sûr de perdre.
  1. Augmenter les files d’attente noyau quand c’est sûr
  • Les taux de connexion élevés bénéficient d’un somaxconn plus grand.
  1. Mesurer, ne pas deviner
  • Relancez les mêmes tests pour des comparaisons avant/après. Notez les changements et les résultats.

Question rapide 2 sur 2

Où le code source et les données montées par liaison doivent-ils être stockés pour obtenir les meilleures performances du système de fichiers dans des conteneurs Linux ?

Le passage indique que les performances sont bien supérieures lorsque les fichiers sont montés par liaison depuis le système de fichiers Linux plutôt que depuis le système de fichiers hôte Windows.

Optimisation sûre via overrides et profils

Gardez votre compose.yml de base simple. Placez le réglage dans un fichier d’override pour pouvoir l’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 bancs d’essai :

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

Activez avec :

COMPOSE_PROFILES=bench docker compose up -d

Liste de contrôle de dépannage

  • Pics de latence après quelques minutes : vérifiez les logs pour des blocages de rotation, augmentez tmpfs pour les caches, confirmez l’absence d’OOM kills.
  • Écritures Postgres lentes : 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 en rafale : augmentez somaxconn et nofile, envisagez le réseau hôte sur Linux pour les tests, vérifiez la politique maxmemory.
  • Throttling CPU : haussez cpus ou réduisez la concurrence ; vérifiez l’isolation via cpuset.
  • E/S fichiers macOS/Windows : remplacez les bind mounts par des volumes nommés pour les chemins chauds ; appliquez :cached ou :delegated uniquement si le bind mount est indispensable.

Conclusion

Maintenez la boucle serrée : définissez les objectifs, établissez une ligne de base, changez une seule chose, re‑mesurez et consignez les résultats. Partez des valeurs par défaut sûres ci‑dessus, privilégiez les volumes nommés pour l’I/O chaud, bornez vos logs et utilisez tmpfs pour les écritures éphémères. Une fois qu’un pilote local montre des gains clairs, capturez‑les dans des overrides ou des profils pour que l’équipe puisse les activer de façon cohérente. Revérifiez vos chiffres à chaque évolution des images, des versions d’OS hôte et des charges de travail afin que votre pile Compose reste rapide et prévisible.

Recherches connexes

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