E-NO
DevOps 11 min de lecture

Docker Compose Monitoring et Alertes : Guide Pratique d'Implémentation

calendar_today Publié : 2026-08-17
update Dernière mise à jour : 2026-08-17
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Docker Compose Monitoring et Alertes : Guide Pratique d'Implémentation ».

Docker Compose simplifie le déploiement d'applications multi-conteneurs, mais son observabilité intégrée se limite à l'état de base des conteneurs et aux journaux. Les charges de travail en production exigent des métriques structurées, des alertes actionnables et des tableaux de bord qui font surface les problèmes avant que les utilisateurs ne les remarquent. Ce guide détaille une pile de monitoring complète pour les environnements Docker Compose utilisant Prometheus, Grafana, Alertmanager et cAdvisor, avec des exemples de configuration concrets, des règles d'alerting et des procédures opérationnelles que vous pouvez adapter à votre stack.

Architecture et Sélection des Composants

Une pile de monitoring pratique pour Docker Compose comprend quatre services principaux :

  • Prometheus récupère les métriques depuis les exporteurs et les points de terminaison d'application, stocke les données de séries temporelles et évalue les règles d'alerting.
  • Alertmanager déduplique, regroupe et route les alertes vers les canaux de notification tels que Slack, PagerDuty ou courriel.
  • Grafana visualise les métriques à travers des tableaux de bord et offre des capacités de requêtage ad hoc.
  • cAdvisor expose l'utilisation des ressources au niveau conteneur (CPU, mémoire, disque, réseau) pour chaque conteneur sur l'hôte.

Des ajouts optionnels mais recommandés incluent Node Exporter pour les métriques au niveau hôte (disque, réseau, charge système) et des exporteurs spécifiques aux applications (par exemple nginx-prometheus-exporter, redis_exporter, postgres_exporter) pour les signaux dorés au niveau service.

Tous les composants s'exécutent comme des conteneurs définis dans un seul fichier docker-compose.monitoring.yml, déployés aux côtés de votre stack applicative ou sur un hôte d'observabilité dédié. Cela maintient le plan de monitoring indépendant des déploiements applicatifs tout en partageant le même réseau Docker pour la découverte de services.

Structure d'Exemple du Fichier Compose

version: "3.8"

services:
  prometheus:
    image: prom/prometheus:v2.53.0
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=30d"
      - "--web.enable-lifecycle"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/rules:/etc/prometheus/rules:ro
      - prometheus_data:/prometheus
    ports:
      - "9090:9090"
    networks:
      - monitoring
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:v0.27.0
    command:
      - "--config.file=/etc/alertmanager/alertmanager.yml"
      - "--storage.path=/alertmanager"
    volumes:
      - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
      - alertmanager_data:/alertmanager
    ports:
      - "9093:9093"
    networks:
      - monitoring
    restart: unless-stopped

  grafana:
    image: grafana/grafana:10.4.0
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD__FILE=/run/secrets/grafana_admin_password
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
      - ./grafana/dashboards:/var/lib/grafana/dashboards:ro
      - grafana_data:/var/lib/grafana
    secrets:
      - grafana_admin_password
    ports:
      - "3000:3000"
    networks:
      - monitoring
    restart: unless-stopped

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.49.1
    command:
      - "--docker_only=true"
      - "--housekeeping_interval=10s"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    ports:
      - "8080:8080"
    networks:
      - monitoring
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:v1.7.0
    command:
      - "--path.rootfs=/host"
    pid: host
    volumes:
      - /:/host:ro
      - /sys:/sys:ro
      - /proc:/proc:ro
    ports:
      - "9100:9100"
    networks:
      - monitoring
    restart: unless-stopped

networks:
  monitoring:
    driver: bridge

volumes:
  prometheus_data:
  alertmanager_data:
  grafana_data:

secrets:
  grafana_admin_password:
    file: ./secrets/grafana_admin_password.txt

Notes opérationnelles clés :

  • Épinglez les tags d'image à des versions spécifiques (pas latest) pour éviter les mises à niveau surprises.
  • Stockez les secrets (mot de passe admin Grafana, URLs webhook Alertmanager) dans les secrets Docker ou un fichier .env exclu du contrôle de version.
  • Montez la configuration en lecture seule (:ro) quand possible pour prévenir les modifications accidentelles.
  • Utilisez des volumes nommés pour les données persistantes (TSDB Prometheus, état Alertmanager, tableaux de bord Grafana) afin que la recréation des conteneurs préserve l'historique.

Configuration Prometheus et Découverte de Services

Prometheus découvre les cibles de scraping via la configuration statique ou la découverte de services Docker. Pour Docker Compose, le mécanisme dockersd détecte automatiquement les conteneurs avec des étiquettes spécifiques, éliminant la gestion manuelle des cibles.

Configuration Prometheus (prometheus/prometheus.yml)

global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    environment: "production"
    compose_project: "myapp"

alerting:
  alertmanagers:
    - static_configs:
        - targets: ["alertmanager:9093"]

rule_files:
  - "rules/*.yml"

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "cadvisor"
    static_configs:
      - targets: ["cadvisor:8080"]

  - job_name: "node-exporter"
    static_configs:
      - targets: ["node-exporter:9100"]

  - job_name: "docker-compose-services"
    dockerswarm_sd_configs:
      - host: unix:///var/run/docker.sock
        role: services
    relabel_configs:
      - source_labels: [__meta_docker_service_label_prometheus_job]
        action: keep
        regex: .+
      - source_labels: [__meta_docker_service_label_prometheus_port]
        action: replace
        target_label: __address__
        regex: (.+)
        replacement: ${1}:${2}
      - source_labels: [__meta_docker_service_label_prometheus_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
        replacement: ${1}

Activation des Métriques d'Application via Étiquettes

Ajoutez les étiquettes de scraping Prometheus à vos services applicatifs dans le docker-compose.yml principal :

services:
  api:
    image: myorg/api:v1.12.0
    ports:
      - "8000:8000"
    labels:
      - "prometheus.job=api"
      - "prometheus.port=8000"
      - "prometheus.path=/metrics"
    networks:
      - app-network
      - monitoring
    deploy:
      replicas: 3

Prometheus découvrira automatiquement le service api, scrapera /metrics sur le port 8000, et taguera les métriques avec job="api". Ce pattern s'étend à des dizaines de services sans toucher à prometheus.yml.

Règles d'Alerting Qui Réduisent le Bruit

Les alertes efficaces se déclenchent sur les symptômes (impact utilisateur) plutôt que sur les causes (état interne). Définissez les règles dans prometheus/rules/ regroupées par domaine.

Alertes Infrastructure (prometheus/rules/infrastructure.yml)

groups:
  - name: infrastructure
    interval: 30s
    rules:
      - alert: ContainerDown
        expr: |
          absent(container_last_seen{job="cadvisor"}) or
          (time() - container_last_seen{job="cadvisor"}) > 60
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Conteneur {{ $labels.name }} hors ligne depuis > 1m"
          description: "Le conteneur {{ $labels.name }} (image: {{ $labels.image }}) n'a pas rapporté de métriques depuis plus de 60 secondes."
          runbook_url: "https://wiki.example.com/runbooks/container-down"

      - alert: ContainerHighCPU
        expr: |
          (rate(container_cpu_usage_seconds_total{job="cadvisor",container!=""}[5m]) /
          container_spec_cpu_quota{job="cadvisor",container!=""} / 100000) > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Conteneur {{ $labels.name }} CPU > 85% depuis 5m"
          description: "Le conteneur {{ $labels.name }} utilise plus de 85% de son quota CPU de façon soutenue. Vérifiez les processus incontrôlés ou les limites sous-dimensionnées."

      - alert: ContainerHighMemory
        expr: |
          (container_memory_usage_bytes{job="cadvisor",container!=""} /
          container_spec_memory_limit_bytes{job="cadvisor",container!=""}) > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Conteneur {{ $labels.name }} mémoire > 85% depuis 5m"
          description: "L'utilisation mémoire du conteneur {{ $labels.name }} dépasse 85% de sa limite. Risque de OOM kill."

      - alert: HostDiskSpaceCritical
        expr: |
          (node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"} /
          node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"}) < 0.1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Espace disque hôte < 10% sur {{ $labels.instance }}"
          description: "Le système de fichiers racine sur {{ $labels.instance }} a moins de 10% d'espace libre. Nettoyez les journaux, images, ou agrandissez le volume."

Signaux Dorés Applicatifs (prometheus/rules/application.yml)

groups:
  - name: application
    interval: 30s
    rules:
      - alert: APIHighErrorRate
        expr: |
          sum(rate(http_requests_total{job="api",code=~"5.."}[2m])) by (job)
          /
          sum(rate(http_requests_total{job="api"}[2m])) by (job)
          > 0.05
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Taux d'erreurs 5xx API > 5% depuis 2m"
          description: "Le service {{ $labels.job }} retourne des erreurs 5xx sur plus de 5% des requêtes. Vérifiez les dépendances amont et les journaux."

      - alert: APIHighLatency
        expr: |
          histogram_quantile(0.95,
            sum(rate(http_request_duration_seconds_bucket{job="api"}[5m])) by (le, job)
          ) > 1.0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Latence p95 API > 1s depuis 5m"
          description: "La latence p95 des requêtes du service {{ $labels.job }} dépasse 1 seconde. Investiguez la base de données, le cache, ou les appels externes."

      - alert: APITrafficDrop
        expr: |
          sum(rate(http_requests_total{job="api"}[5m])) by (job) < 0.1
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Trafic API proche de zéro depuis 10m"
          description: "Le service {{ $labels.job }} reçoit < 0.1 req/s. Problème de routage, échec de déploiement, ou panne amont possible."

Routage Alertmanager (alertmanager/alertmanager.yml)

global:
  resolve_timeout: 5m
  slack_api_url: "https://hooks.slack.com/services/XXX/YYY/ZZZ"

route:
  group_by: ["alertname", "job", "severity"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: "slack-critical"
  routes:
    - match:
        severity: "critical"
      receiver: "slack-critical"
      continue: true
    - match:
        severity: "warning"
      receiver: "slack-warning"
      group_interval: 15m
      repeat_interval: 12h

receivers:
  - name: "slack-critical"
    slack_configs:
      - channel: "#alertes-critiques"
        title: "[{{ .Status }}] {{ .GroupLabels.alertname }}"
        text: "{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}"
        send_resolved: true
        icon_emoji: ":fire:"
  - name: "slack-warning"
    slack_configs:
      - channel: "#alertes-avertissements"
        title: "[{{ .Status }}] {{ .GroupLabels.alertname }}"
        text: "{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}"
        send_resolved: true
        icon_emoji: ":warning:"

inhibit_rules:
  - source_match:
      severity: "critical"
    target_match:
      severity: "warning"
    equal: ["job", "instance"]

Cette configuration route les alertes critiques vers un canal à haute visibilité avec des intervalles de répétition courts, tandis que les avertissements vont vers un canal à moindre bruit avec un regroupement plus long. L'inhibition prévient les tempêtes d'avertissements quand une alerte critique couvre déjà le même service.

Tableaux de Bord Grafana et Provisioning

Provisionnez les tableaux de bord comme du code pour qu'ils soient versionnés aux côtés de l'infrastructure. Grafana lit le JSON des tableaux de bord depuis un répertoire monté au démarrage.

Configuration de Provisioning (grafana/provisioning/dashboards/dashboard-provider.yml)

apiVersion: 1

providers:
  - name: "Docker Compose Monitoring"
    orgId: 1
    folder: "Infrastructure"
    type: file
    disableDeletion: false
    updateIntervalSeconds: 30
    allowUiUpdates: false
    options:
      path: /var/lib/grafana/dashboards

Panneaux Clés des Tableaux de Bord

Créez ou importez des tableaux de bord couvrant :

  1. Vue d'ensemble des conteneurs : Tableau de tous les conteneurs avec statut, CPU %, mémoire %, nombre de redémarrages et temps de fonctionnement. Utilisez container_last_seen, container_cpu_usage_seconds_total, container_memory_usage_bytes, et container_start_time_seconds depuis cAdvisor.
  2. Saturation des ressources : Carte de chaleur de l'utilisation CPU et mémoire à travers les services dans le temps. Repérez les tendances avant d'atteindre les limites.
  3. Taux de requêtes, Erreurs, Durée (RED) : Pour chaque service instrumenté, affichez requêtes/seconde, taux d'erreur (5xx / total), et latence p50/p95/p99 depuis les points de terminaison /metrics d'application.
  4. Ressources hôte : Panneaux Node Exporter pour E/S disque, débit réseau, charge moyenne, et utilisation des systèmes de fichiers.
  5. Statut des alertes : Tableau des alertes en cours de déclenchement depuis l'API Alertmanager (/api/v2/alertes) avec boutons de silence.

Stockez les fichiers JSON des tableaux de bord dans grafana/dashboards/ et commitez-les. Au redémarrage de Grafana, les tableaux de bord apparaissent automatiquement sans import manuel.

Procédures Opérationnelles

Déploiement de la Stack

# Créer le répertoire secrets et générer le mot de passe Grafana
mkdir -p secrets
openssl rand -base64 32 > secrets/grafana_admin_password.txt
chmod 600 secrets/grafana_admin_password.txt

# Déployer la stack de monitoring
docker compose -f docker-compose.monitoring.yml up -d

# Vérifier que tous les services sont sains
docker compose -f docker-compose.monitoring.yml ps

Vérification de la Collecte de Métriques

# Vérifier les cibles Prometheus
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job: .labels.job, instance: .labels.instance, health: .health}'

# Requêter une métrique d'exemple
curl -s "http://localhost:9090/api/v1/query?query=container_cpu_usage_seconds_total" | jq '.data.result[0]'

# Vérifier le statut Alertmanager
curl -s http://localhost:9093/api/v2/status | jq '.'

Ajout d'un Nouveau Service au Monitoring

  • Ajoutez les étiquettes Prometheus au service dans votre docker-compose.yml applicatif.
  • Assurez-vous que le service rejoint le réseau monitoring.
  • Redéployez la stack applicative : docker compose up -d.
  • Vérifiez que la cible apparaît dans l'UI Prometheus (Status → Targets) dans les 30 secondes.
  • Créez ou mettez à jour les règles d'alerting si le service expose de nouveaux SLI.
  • Ajoutez des panneaux au tableau de bord Grafana pertinent.

Rotation des Secrets

# Générer un nouveau mot de passe Grafana
openssl rand -base64 32 > secrets/grafana_admin_password.txt.new
# Mettre à jour le secret (nécessite un redémarrage de la stack pour que Grafana le prenne en compte)
mv secrets/grafana_admin_password.txt.new secrets/grafana_admin_password.txt
docker compose -f docker-compose.monitoring.yml up -d --force-recreate grafana

Sauvegarde et Reprise Après Sinistre

  • Données Prometheus : Instantané via API (POST /api/v1/admin/tsdb/snapshot) ou arrêt du conteneur et archivage du volume prometheus_data.
  • Tableaux de bord Grafana : Déjà dans Git via le provisioning. Exportez le JSON des tableaux de bord depuis l'UI comme sauvegarde.
  • Configuration Alertmanager : Dans Git. L'état des silences stocké dans le volume alertmanager_data ; recréation depuis la config à la restauration.

Testez la restauration trimestriellement : lancez un hôte frais, montez les sauvegardes de volumes, démarrez la stack, vérifiez que les tableaux de bord affichent l'historique et que les alertes s'évaluent correctement.

Modes de Défaillance et Atténuations

Mode de défaillanceDétectionAtténuation
Prometheus OOMcontainer_memory_usage_bytes près de la limite, échecs de scrapingAugmenter --storage.tsdb.retention.time, ajouter memory_limit au Compose, activer la compression WAL
Alertmanager hors ligneAucune alerte livrée, cible Prometheus alertmanager non saineExécuter 2+ répliques Alertmanager en mode HA avec mesh gossip partagé
cAdvisor conteneurs manquantsGaps container_last_seen, alertes "ContainerDown"S'assurer que cAdvisor a --docker_only=true et accès au socket Docker
Dérive tableaux de bord GrafanaModifications UI non reflétées dans GitDéfinir allowUiUpdates: false dans le provisioning ; imposer workflow PR pour changements tableaux de bord
Spam de journaux erreurs scrapeJournaux Prometheus, scrape_duration_seconds élevéCorriger le point de terminaison /metrics cible, ajuster scrape_timeout, vérifier politiques réseau

Conclusion

Le monitoring des charges de travail Docker Compose exige plus que docker stats et la consultation de journaux. Une stack construite sur Prometheus, Alertmanager, Grafana et cAdvisor fournit une visibilité au niveau service, des alertes actionnables et une analyse historique sans installation d'agent ni modification d'hôte. Le déploiement basé sur Compose garde les opérations simples : configuration versionnée, gestion des secrets via secrets Docker, et mise à l'échelle indépendante du plan d'observabilité. Commencez par les alertes infrastructure (santé des conteneurs, saturation des ressources), ajoutez les signaux dorés applicatifs au fur et à mesure que les services exposent des points de terminaison /metrics, et itérez les tableaux de bord basés sur les rétrospectives d'incidents. Traitez le code de monitoring comme du code applicatif — révisez, testez, versionnez, et déployez à travers le même pipeline.

Recherches connexes

Score de qualité de l’article

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