Monitoring et alerting pour workloads Docker : détecter les pannes avant les utilisateurs
Le monitoring et l’alerting d’applications conteneurisées ne se résument pas à « vérifier que le conteneur tourne ». Un conteneur peut être up tout en étant inutile (deadlock, saturation CPU, fuite mémoire, pool de connexions épuisé, latence énorme, erreurs 5xx, disque plein, etc.). L’objectif de ce tutoriel est de construire une chaîne complète et pragmatique pour détecter les pannes avant les utilisateurs, avec des commandes réelles, des métriques actionnables, des alertes pertinentes et des tests de panne.
Ce guide se concentre sur Docker (standalone), mais les principes sont identiques en Swarm/Kubernetes.
1) Principes : ce qu’il faut vraiment monitorer
1.1 Les 4 couches indispensables
- Hôte (node)
CPU, RAM, swap, disque, I/O, réseau, saturation, erreurs kernel, pression mémoire. - Runtime conteneur (Docker)
Nombre de conteneurs, restarts, OOMKills, limites cgroups, usage CPU/mémoire par conteneur. - Application
Latence, taux d’erreur, throughput, queues, connexions DB, temps de réponse, exceptions. - Expérience utilisateur / SLO
Disponibilité, p95/p99, taux d’erreur, apdex, objectifs (SLO) et budget d’erreur.
1.2 Golden Signals (recommandé)
Pour chaque service, essayez d’avoir au minimum :
- Latency : p50/p95/p99, et pas seulement la moyenne.
- Traffic : requêtes/s, messages/s, jobs/s.
- Errors : 5xx, timeouts, exceptions, erreurs métier critiques.
- Saturation : CPU throttling, mémoire proche de la limite, pool DB saturé, file de messages qui gonfle.
2) Outils : une stack simple et efficace
Une combinaison classique et robuste :
- Prometheus : collecte et requêtage de métriques.
- Alertmanager : routage des alertes (email, Slack, Teams, webhook…).
- Grafana : dashboards.
- cAdvisor : métriques conteneurs (CPU/RAM/FS/Network).
- node_exporter : métriques de l’hôte (CPU, disque, réseau).
- Blackbox exporter : checks externes (HTTP/TCP/ICMP).
- (Optionnel) Loki + Promtail : logs centralisés (utile pour corréler).
Ce tutoriel installe Prometheus/Grafana/Alertmanager + exporters, puis configure des alertes utiles.
3) Pré-requis et vérifications Docker
Sur votre serveur (Linux recommandé), vérifiez Docker :
docker version
docker info
Vérifiez l’usage actuel :
docker ps
docker stats --no-stream
docker events --since 10m
Inspectez un conteneur pour voir les limites :
docker inspect --format '{{json .HostConfig}}' <container_name_or_id> | jq
Si jq n’est pas installé :
sudo apt-get update && sudo apt-get install -y jq
4) Déploiement de la stack monitoring (Prometheus + Grafana + Alertmanager)
Vous pouvez tout lancer avec docker compose. Comme on vous demande « Markdown only » et des commandes réelles, voici une approche reproductible : vous créez les fichiers, puis vous lancez.
4.1 Arborescence
mkdir -p monitoring/{prometheus,alertmanager,grafana,blackbox}
cd monitoring
4.2 Réseau Docker dédié
docker network create monitoring
4.3 Prometheus : configuration
Créez prometheus/prometheus.yml :
cat > prometheus/prometheus.yml <<'EOF'
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules/*.rules.yml
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["prometheus:9090"]
- job_name: "node_exporter"
static_configs:
- targets: ["node_exporter:9100"]
- job_name: "cadvisor"
static_configs:
- targets: ["cadvisor:8080"]
- job_name: "blackbox"
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://example.com/
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox:9115
EOF
Créez un dossier de règles :
mkdir -p prometheus/rules
4.4 Alertmanager : configuration
Créez alertmanager/alertmanager.yml (exemple webhook ; adaptez à Slack/Email) :
cat > alertmanager/alertmanager.yml <<'EOF'
global:
resolve_timeout: 5m
route:
receiver: "webhook-default"
group_by: ["alertname", "job", "instance"]
group_wait: 30s
group_interval: 5m
repeat_interval: 2h
receivers:
- name: "webhook-default"
webhook_configs:
- url: "http://your-webhook-endpoint.local/alert"
send_resolved: true
EOF
Pour tester rapidement sans webhook réel, vous pouvez utiliser un conteneur qui logge les requêtes HTTP (voir section tests).
4.5 Blackbox exporter : configuration
Créez blackbox/blackbox.yml :
cat > blackbox/blackbox.yml <<'EOF'
modules:
http_2xx:
prober: http
timeout: 5s
http:
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
valid_status_codes: []
method: GET
preferred_ip_protocol: "ip4"
EOF
4.6 Lancement via Docker Compose
Créez compose.monitoring.yml :
cat > compose.monitoring.yml <<'EOF'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
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:latest
container_name: alertmanager
command:
- "--config.file=/etc/alertmanager/alertmanager.yml"
volumes:
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
ports:
- "9093:9093"
networks: ["monitoring"]
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
networks: ["monitoring"]
restart: unless-stopped
node_exporter:
image: prom/node-exporter:latest
container_name: node_exporter
pid: host
command:
- "--path.rootfs=/host"
volumes:
- "/:/host:ro,rslave"
ports:
- "9100:9100"
networks: ["monitoring"]
restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
privileged: true
volumes:
- "/:/rootfs:ro"
- "/var/run:/var/run:rw"
- "/sys:/sys:ro"
- "/var/lib/docker/:/var/lib/docker:ro"
- "/dev/disk/:/dev/disk:ro"
ports:
- "8080:8080"
networks: ["monitoring"]
restart: unless-stopped
blackbox:
image: prom/blackbox-exporter:latest
container_name: blackbox
volumes:
- ./blackbox/blackbox.yml:/etc/blackbox_exporter/config.yml:ro
command:
- "--config.file=/etc/blackbox_exporter/config.yml"
ports:
- "9115:9115"
networks: ["monitoring"]
restart: unless-stopped
networks:
monitoring:
external: true
volumes:
prometheus_data:
grafana_data:
EOF
Lancez :
docker compose -f compose.monitoring.yml up -d
docker ps
Accès :
- Prometheus : http://localhost:9090
- Alertmanager : http://localhost:9093
- Grafana : http://localhost:3000 (admin/admin)
5) Ajouter des alertes utiles (pas du bruit)
Créer des alertes « bêtes » du type CPU > 80% est souvent une source de fatigue (alert fatigue). Préférez des alertes orientées impact (erreurs, latence, indisponibilité) et risque (disque presque plein, OOM, restarts en boucle).
5.1 Règles Prometheus (fichier)
Créez prometheus/rules/docker-workloads.rules.yml :
cat > prometheus/rules/docker-workloads.rules.yml <<'EOF'
groups:
- name: docker-workloads
rules:
- alert: InstanceDown
expr: up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Cible Prometheus down ({{ $labels.job }} / {{ $labels.instance }})"
description: "Prometheus n'arrive plus à scrapper la cible depuis 2 minutes."
- alert: HostDiskAlmostFull
expr: (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) < 0.10
for: 10m
labels:
severity: warning
annotations:
summary: "Disque presque plein sur {{ $labels.instance }} ({{ $labels.mountpoint }})"
description: "Moins de 10% d'espace libre depuis 10 minutes."
- alert: HostDiskWillFillSoon
expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 24*3600) < 0
for: 30m
labels:
severity: critical
annotations:
summary: "Disque va se remplir dans < 24h sur {{ $labels.instance }} ({{ $labels.mountpoint }})"
description: "Projection sur 24h basée sur les 6 dernières heures."
- alert: ContainerRestartsHigh
expr: increase(container_start_time_seconds[15m]) > 3
for: 0m
labels:
severity: warning
annotations:
summary: "Redémarrages fréquents détectés (cadvisor)"
description: "Un ou plusieurs conteneurs semblent redémarrer souvent (augmentation de start_time_seconds). À investiguer via docker ps / logs."
- alert: ContainerCPUThrottlingHigh
expr: rate(container_cpu_cfs_throttled_seconds_total[5m]) > 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "CPU throttling élevé ({{ $labels.container_label_com_docker_compose_service }})"
description: "Le conteneur est fortement bridé par CFS. Vérifiez limites CPU et charge."
- alert: HostMemoryPressure
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 0.90
for: 10m
labels:
severity: warning
annotations:
summary: "Pression mémoire élevée sur {{ $labels.instance }}"
description: "Plus de 90% de la mémoire est consommée (MemAvailable faible). Risque d'OOM."
- alert: EndpointDownBlackbox
expr: probe_success == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Endpoint indisponible ({{ $labels.instance }})"
description: "Le check blackbox échoue depuis 2 minutes."
EOF
Rechargez Prometheus (redémarrage simple) :
docker restart prometheus
Vérifiez dans Prometheus > Status > Rules.
Remarque importante :
container_start_time_secondsn’est pas un compteur, doncincrease()est une approximation pour détecter des changements. Selon versions cAdvisor, vous pouvez préférer des métriques de restart si disponibles dans votre environnement, ou instrumenter via Docker events (voir section 9).
6) Dashboards Grafana : ce qu’il faut afficher
6.1 Ajouter Prometheus comme datasource
Dans Grafana :
- Configuration → Data sources → Add data source → Prometheus
- URL :
http://prometheus:9090(si Grafana est sur le même réseau Docker) - Save & Test
6.2 Dashboards recommandés
Vous pouvez importer des dashboards communautaires (ID Grafana). Exemples souvent utilisés :
- Node Exporter Full
- cAdvisor / Docker
- Blackbox exporter
Import manuel :
- Dashboards → New → Import → collez l’ID → choisissez la datasource.
6.3 Les panneaux qui aident vraiment en incident
Pour chaque service applicatif, essayez d’avoir :
- Taux de requêtes (RPS)
- Taux d’erreur (5xx, timeouts)
- Latence p95/p99
- Saturation (CPU throttling, mémoire proche limite)
- Restarts / OOM
- Dépendances (DB, cache, broker) : connexions, latence, erreurs
7) Instrumenter l’application : métriques et healthchecks
Le monitoring infra est nécessaire mais insuffisant. Pour détecter « avant les utilisateurs », il faut des métriques applicatives et des checks.
7.1 Healthcheck Docker
Ajoutez un HEALTHCHECK dans l’image ou via compose (si vous gérez vos Dockerfiles). Exemple Dockerfile :
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD wget -qO- http://localhost:8080/health || exit 1
Vérification :
docker inspect --format '{{.State.Health.Status}}' <container>
docker ps --format 'table {{.Names}}\t{{.Status}}'
Un healthcheck doit tester une dépendance minimale (ex: DB) si votre service ne peut pas fonctionner sans. Sinon vous aurez des conteneurs « healthy » mais un service inutilisable.
7.2 Exposer des métriques Prometheus
Exemple conceptuel (sans code complet) : exposez /metrics et /health. Ensuite ajoutez un scrape_config dans Prometheus pour votre service :
# Exemple: votre service écoute sur 8080 et expose /metrics
# Si le service est dans Docker et sur le réseau monitoring, vous pouvez le cibler par nom de conteneur.
Ajoutez dans prometheus/prometheus.yml :
grep -n "scrape_configs" -n prometheus/prometheus.yml
Éditez (avec nano/vim) et ajoutez :
- job_name: "app"
static_configs:
- targets: ["mon_app:8080"]
Puis :
docker restart prometheus
8) Alerting orienté SLO : erreurs et latence
Les alertes les plus utiles sont celles qui indiquent un impact utilisateur imminent. Si votre application expose des métriques HTTP (ex: http_requests_total, http_request_duration_seconds_bucket), vous pouvez alerter sur :
- Taux d’erreur > X% sur 5–10 min
- Latence p95 > seuil sur 10 min
- Budget d’erreur consommé trop vite (approche SRE)
8.1 Exemples de requêtes PromQL (à adapter)
Taux d’erreur (5xx)
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
Latence p95 (histogramme)
histogram_quantile(
0.95,
sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
)
Si vous n’avez pas d’histogrammes, commencez par en ajouter. Les moyennes masquent les queues de distribution (p95/p99).
9) Détecter les redémarrages, crashloops et OOM de façon fiable
9.1 Observer les événements Docker
Docker émet des événements utiles :
docker events --since 1h --filter 'type=container' --filter 'event=die'
docker events --since 1h --filter 'event=oom'
Pour investiguer un conteneur qui redémarre :
docker ps -a --filter "name=mon_app" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
docker logs --since 30m mon_app
docker inspect mon_app --format '{{json .State}}' | jq
9.2 Exporter des événements Docker vers Prometheus (approche simple)
Il existe des exporters dédiés (ex: docker daemon metrics, ou des sidecars). Une solution pragmatique : un petit agent qui convertit les événements en métriques. Si vous ne voulez pas développer, vous pouvez au minimum :
- centraliser les logs (Loki/ELK) et alerter sur patterns (OOMKilled, panic, segfault)
- ou utiliser un exporter existant (selon votre politique).
Même sans exporter, gardez des runbooks : « si alerte X, exécuter commandes Y ».
10) Checks externes : Blackbox exporter (HTTP/TCP)
Le blackbox exporter simule un utilisateur externe (ou un point de contrôle) : DNS, TLS, latence, code HTTP.
10.1 Tester manuellement une probe
Depuis Prometheus, vous pouvez requêter :
probe_successprobe_duration_secondsprobe_http_status_codeprobe_ssl_earliest_cert_expiry
Exemple : vérifier l’expiration TLS :
(probe_ssl_earliest_cert_expiry - time()) / 86400
Alerte typique : certificat expire dans < 14 jours.
11) Sécurité et robustesse : éviter que le monitoring soit le maillon faible
11.1 Persistance
Vous avez déjà des volumes prometheus_data et grafana_data. Assurez-vous que le disque n’est pas éphémère et qu’il y a de la place.
11.2 Rétention Prometheus
Par défaut, Prometheus garde un certain historique. Vous pouvez contrôler la rétention :
Dans le service Prometheus, ajoutez par exemple :
# Exemple (à mettre dans command):
# --storage.tsdb.retention.time=15d
11.3 Authentification
- Grafana : changez le mot de passe admin.
- Prometheus/Alertmanager : idéalement derrière un reverse proxy (Nginx/Traefik) avec auth, ou réseau privé.
12) Exercices de chaos (tests) : valider que vos alertes marchent
Un système d’alerting non testé est un système qui échoue en prod. Faites des tests contrôlés.
12.1 Simuler une panne applicative
Stoppez un service :
docker stop mon_app
Attendez 2–3 minutes :
up{job="app"}doit passer à 0 (si scrappé)probe_successdoit passer à 0 (si blackbox le cible)- Alertmanager doit recevoir l’alerte
Relancez :
docker start mon_app
12.2 Simuler une saturation CPU
Dans un conteneur (ou sur l’hôte), vous pouvez générer de la charge. Exemple sur l’hôte :
sudo apt-get install -y stress-ng
stress-ng --cpu 2 --timeout 120s
Surveillez :
node_cpu_seconds_total(via Grafana)container_cpu_usage_seconds_total(cAdvisor)- throttling si limites CPU
12.3 Simuler une pression disque
Créez un gros fichier (attention à ne pas casser votre machine) :
df -h
fallocate -l 2G /tmp/bigfile.test
df -h
rm -f /tmp/bigfile.test
Validez l’alerte « disque presque plein » si vous ajustez le seuil.
13) Runbooks : que faire quand une alerte tombe
Une alerte sans procédure = temps perdu. Ajoutez dans vos annotations (ou documentation) des étapes.
13.1 Exemple de runbook pour « EndpointDownBlackbox »
- Vérifier si l’endpoint répond depuis le serveur :
curl -vk https://example.com/ -m 5 - Vérifier DNS :
dig +short example.com - Vérifier reverse proxy / conteneur :
docker ps docker logs --since 10m reverse-proxy - Vérifier certificats :
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
13.2 Exemple de runbook pour « HostMemoryPressure »
- Voir mémoire :
free -h vmstat 1 5 - Top processus :
ps aux --sort=-%mem | head -n 15 - Conteneurs gourmands :
docker stats --no-stream - Vérifier OOM dans kernel :
dmesg -T | egrep -i 'oom|killed process' | tail -n 50
14) Bonnes pratiques d’alerting (pour éviter le bruit)
- Alertez sur l’impact, pas sur des symptômes isolés.
Exemple : « taux d’erreur > 2% » est souvent mieux que « CPU > 80% ». - Utilisez
for:pour filtrer les spikes.
Un pic de 10 secondes ne mérite pas toujours un réveil. - Définissez des niveaux (warning/critical) et des canaux.
Warning → canal équipe, Critical → astreinte. - Dédupliquez (grouping Alertmanager) et mettez un
repeat_intervalraisonnable. - Ajoutez du contexte : lien Grafana, commande de diagnostic, owner du service.
- Révisez les alertes après chaque incident : lesquelles ont aidé, lesquelles ont fait du bruit.
15) Dépannage fréquent
15.1 Prometheus ne scrape pas une cible Docker
- Vérifiez réseau : la cible est-elle sur le réseau
monitoring?docker network inspect monitoring | jq '.[0].Containers | keys' - Vérifiez le nom/port :
docker exec -it prometheus sh -c "wget -qO- http://cadvisor:8080/metrics | head" - Vérifiez
Targetsdans Prometheus : http://localhost:9090/targets
15.2 cAdvisor ne montre pas certains conteneurs
- Vérifiez les mounts
/var/lib/docker,/sys,/var/run. - Vérifiez les permissions (souvent besoin de
privileged: true).
15.3 Alertmanager ne reçoit rien
- Vérifiez dans Prometheus : Status → Alertmanagers
- Vérifiez logs :
docker logs --since 30m prometheus docker logs --since 30m alertmanager - Vérifiez la config
alerting:et la résolution DNSalertmanager.
16) Aller plus loin (recommandations réalistes)
- Logs : ajoutez Loki + Promtail pour corréler métriques ↔ logs.
- Traces : OpenTelemetry + Tempo/Jaeger pour diagnostiquer la latence.
- SLO : formalisez des objectifs (ex: 99.9% succès sur 30j) et alertez sur burn rate.
- Multi-environnements : séparez prod/staging, labels cohérents (
env,service,team). - Backups : sauvegardez les volumes Grafana (dashboards) et la config.
Conclusion
Mettre en place un monitoring Docker efficace consiste à :
- Collecter métriques hôte + conteneurs + endpoints externes.
- Instrumenter l’application (métriques + healthchecks).
- Alerter intelligemment (impact/SLO, pas de bruit).
- Tester régulièrement les alertes par des pannes contrôlées.
- Documenter via runbooks pour réduire le MTTR.
Avec Prometheus + Alertmanager + Grafana + node_exporter + cAdvisor + blackbox exporter, vous avez une base solide pour détecter les pannes avant vos utilisateurs—à condition de choisir des signaux pertinents et de valider votre chaîne d’alerte en conditions réelles.