Introduction
Une bonne surveillance Docker répond à trois questions clés pendant un incident : qu'est-ce qui a changé, qu'est-ce qui casse, et où corriger. Pour la majorité des équipes, cela signifie observer le CPU et la mémoire des conteneurs, les redémarrages et les OOM kills, la dérive d'images, ainsi que la pression réseau ou disque. Ce guide vous propose un pilote ciblé sur un hôte unique pour démontrer de la valeur très vite, puis l'étendre en confiance. Vous y trouverez les métriques à collecter, des règles d'alerte concrètes, des signaux de logs, des tableaux de bord, des étapes de vérification, des modes de panne courants et des instructions de retour arrière.
L'approche est volontairement simple : activer l'endpoint de métriques du Docker Engine, ajouter cAdvisor pour les stats par conteneur, scrapper avec Prometheus, router les alertes via Alertmanager et appliquer une rotation de logs. Toutes les étapes sont sûres à tester en local avant tout déploiement multi-hôtes.
Inventaire des versions et de l'environnement
Avant de changer quoi que ce soit, dressez un inventaire pour mesurer les améliorations et revenir en arrière en sécurité.
- Relever les versions et la topologie
- Exécuter :
docker versionet conserver les versions client et serveur. - Exécuter :
docker infoet noter Storage Driver, Logging Driver, Cgroup Driver et le nombre de conteneurs en cours d'exécution. - OS :
uname -aet/etc/os-release. - Nom d'hôte et IP :
hostname -fetip -br a. - Réseaux :
docker network lsetdocker network inspect <network>pour les réseaux de production. - Configuration de base
- Sauvegarder :
sudo cp -a /etc/docker/daemon.json /etc/docker/daemon.json.bak.$(date +%s) 2>/dev/null || true - Valider le JSON :
sudo sh -c 'test -f /etc/docker/daemon.json && jq . /etc/docker/daemon.json >/dev/null' || echo ok - Noter les options de logs actuelles :
docker info | grep -i 'Logging Driver' -A2 - Accès et sécurité
- Vérifier vos droits sudo pour redémarrer Docker :
sudo systemctl status docker. - Fenêtre de maintenance : le redémarrage du démon est bref mais peut interrompre des opérations de contrôle (start/stop, pulls). Les conteneurs en cours tournent en général sans coupure ; planifiez en période creuse.
Chemin de configuration sécurisé
Objectif : un pilote sur un seul hôte, endpoints liés à localhost, collecte confirmée, puis quelques alertes ciblées. Gardez les identifiants et l'exposition réseau au minimum.
Choisir un périmètre de pilote étroit
| Choix | Raison | Impact |
|---|---|---|
| Hôte Docker unique | Simple à raisonner et à annuler | Rayon d'action minimal |
| Endpoints liés à localhost | Évite d'exposer des métriques au réseau | Réduit le risque |
| cAdvisor pour stats conteneurs | Stable, métriques fines | Alerte au niveau conteneur |
| Prometheus + Alertmanager | Config fichiers simples | Vérifiable rapidement |
Configurer les métriques Docker et la rotation des logs
- Créez ou éditez
/etc/docker/daemon.jsonavec des valeurs prudentes. Exemple :
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"experimental": true,
"metrics-addr": "127.0.0.1:9323"
}
Remarques :
experimentaldoit être à true pour exposer l'endpoint de métriques.- Lier sur
127.0.0.1évite l'exposition réseau ; scrappez localement. - Si vous utilisez déjà un log driver non par défaut, conservez-le et ajoutez seulement les paramètres de métriques.
- Validez le JSON et redémarrez Docker en sécurité :
sudo jq . /etc/docker/daemon.json >/dev/nullsudo systemctl restart docker- Vérifier :
curl -s http://127.0.0.1:9323/metrics | head -n 5doit imprimer des lignes au format Prometheus.
Ajouter cAdvisor pour les métriques par conteneur
Exécutez cAdvisor avec montages en lecture seule. L'exemple ci-dessous reste local et n'expose pas l'UI vers l'extérieur.
sudo docker run -d \
--name=cadvisor \
--restart unless-stopped \
-p 127.0.0.1:8080:8080 \
-v /:/rootfs: ro \
-v /var/run:/var/run: ro \
-v /sys:/sys: ro \
-v /var/lib/docker/:/var/lib/docker: ro \
gcr.io/cadvisor/cadvisor: latest
Vérifier : curl -s http://127.0.0.1:8080/metrics | head -n 5
Lancer un pilote Prometheus et Alertmanager en local
Utilisez des fichiers de configuration locaux pour tout auditer et revenir en arrière facilement.
- Créez
./prometheus/avec :
prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/alerts.yml
scrape_configs:
- job_name: 'docker-engine'
static_configs:
- targets: ['127.0.0.1:9323']
- job_name: 'cadvisor'
static_configs:
- targets: ['127.0.0.1:8080']
alerts.ymlavec des règles ciblées :
# CPU proche d'un cœur plein pendant 5m
- alert: ContainerHighCPU
expr: rate(container_cpu_usage_seconds_total{container!=""}[5m]) > 0.9
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.container }} CPU élevé"
description: "CPU du conteneur > 90% d'un cœur pendant 5m"
# Mémoire > 90% de la limite (si une limite est définie)
- alert: ContainerMemoryNearLimit
expr: (container_memory_working_set_bytes{container!=""} / container_spec_memory_limit_bytes{container!=""} > 0.9) and on(container) (container_spec_memory_limit_bytes{container!=""} > 0)
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.container }} mémoire proche de la limite"
description: "Working set > 90% de la limite depuis 5m"
# Détection de crash loop via changements d'heure de démarrage
- alert: ContainerCrashLoop
expr: changes(container_start_time_seconds{container!=""}[5m]) > 2
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.container }} en crash loop"
description: "Redémarrages multiples en 5m"
# Signal d'OOM kill (si exposé par cAdvisor)
- alert: ContainerOOMKilled
expr: increase(container_oom_events_total{container!=""}[5m]) > 0
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.container }} OOM tué"
description: "Un ou plusieurs événements OOM dans les 5 dernières minutes"
- Démarrez Prometheus, lié à localhost :
sudo docker run -d \
--name=prometheus \
--restart unless-stopped \
-p 127.0.0.1:9090:9090 \
-v $(pwd)/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml: ro \
-v $(pwd)/prometheus/alerts.yml:/etc/prometheus/alerts.yml: ro \
prom/prometheus: latest
- Démarrez un Alertmanager minimal et routez en local. Créez
./alertmanager/alertmanager.yml:
route:
receiver: 'stdout'
receivers:
- name: 'stdout'
webhook_configs:
- url: 'http://127.0.0.1:5001/'
send_resolved: true
Lancer Alertmanager :
sudo docker run -d \
--name=alertmanager \
--restart unless-stopped \
-p 127.0.0.1:9093:9093 \
-v $(pwd)/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml: ro \
prom/alertmanager: latest
Pour un récepteur local rapide, exécutez dans un autre terminal :
python3 -m http.server 5001
Vous pourrez ensuite configurer un webhook d'équipe (chat/email) après vérification locale.
Signaux et métriques clés à surveiller
| Signal | Pourquoi | Exemple |
|---|---|---|
| Saturation CPU | Détecte processus débridés ou limites inadaptées | rate(container_cpu_usage_seconds_total{container!=""}[5m]) |
| Pression mémoire | Repère fuites et risque d'OOM | container_memory_working_set_bytes{container!=""} |
| Redémarrages | Détecte crash loops et instabilité | changes(container_start_time_seconds{container!=""}[5m]) |
| OOM kills | Page critique immédiate | increase(container_oom_events_total{container!=""}[5m]) |
| Santé de l'engine | Vérifie le plan de contrôle Docker | curl -s 127.0.0.1:9323/metrics | head |
Signaux de logs Docker utiles
- Sorties et redémarrages des conteneurs :
docker ps --format '{{.Names}} {{.Status}}'etdocker inspect -f '{{.Name}} RestartCount={{.RestartCount}}' <container> - Indicateur OOMKilled :
docker inspect -f '{{.Name}} OOMKilled={{.State.OOMKilled}}' <container> - Événements au niveau engine :
docker events --since 10m --filter type=container --filter event=oom --filter event=die - Erreurs applicatives :
docker logs --since 10m <container>; cherchez les traces et le débit d'erreurs par minute.
Vérifications et diagnostics
Validez chaque brique avant d'avancer. Les étapes suivantes sont ciblées et réversibles.
1) Vérifier les endpoints de métriques
- Engine :
curl -s 127.0.0.1:9323/metrics | grep -m1 ^#doit montrer une ligne HELP/TYPE. - cAdvisor :
curl -s 127.0.0.1:8080/metrics | grep -m1 ^#doit afficher des en-têtes Prometheus. - Cibles Prometheus : ouvrez
http://127.0.0.1:9090/targets; les deux jobs doivent être UP.
2) Déclencher une alerte CPU
Créez un conteneur qui consomme du CPU :
docker run -d --name cpuhog --rm alpine:3 sh -c 'while :; do :; done'
- Requête Prometheus :
rate(container_cpu_usage_seconds_total{container="cpuhog"}[5m])doit tendre vers 1.0 sur un cœur. - Sous 5 à 10 minutes, l'alerte ContainerHighCPU doit se déclencher.
- Arrêt :
docker rm -f cpuhog
3) Déclencher une alerte de crash loop
Démarrez un conteneur qui sort immédiatement et redémarre :
docker run -d --name crashloop --restart always alpine:3 sh -c 'echo boom; sleep 1; exit 1'
- Vérifier les redémarrages :
docker ps --format '{{.Names}} {{.Status}}' | grep crashloop - Requête :
changes(container_start_time_seconds{container="crashloop"}[5m]) - L'alerte ContainerCrashLoop doit se déclencher. Nettoyage :
docker rm -f crashloop
4) Optionnel : simuler une pression mémoire
Si vous avez une image de test qui peut allouer de la mémoire, lancez-la avec une limite faible et essayez de la dépasser. Vérifiez si container_oom_events_total augmente et si les alertes se déclenchent. Si vous ne pouvez pas simuler d'OOM en sécurité, validez en inspectant un conteneur après un OOM connu :
docker inspect -f '{{.Name}} OOMKilled={{.State.OOMKilled}}' <container>
5) Valider le routage des alertes
- Ouvrez
http://127.0.0.1:9093/#/alertspour voir les alertes actives. - Confirmez que votre récepteur local reçoit des POST lors du déclenchement.
- Si vous intégrez un chat/email, baissez temporairement les seuils et confirmez une seule notification.
Modes d'échec courants et reprise
- Endpoint de métriques injoignable
- Symptôme :
curl 127.0.0.1:9323/metricséchoue. - Cause :
experimentalnon activé, port déjà utilisé, erreur de syntaxe dans daemon.json. - Correctif : valider le JSON avec
jq ., mettreexperimental: true, confirmermetrics-addr, redémarrer Docker.
- Problèmes de permissions/montages cAdvisor
- Symptôme : cible cAdvisor DOWN ou métriques manquantes.
- Cause : montages absents ou erreurs de lecture sur
/var/lib/dockerou/sys. - Correctif : garantir les montages en lecture seule, redémarrer cAdvisor.
- Alertes bavardes ou dupliquées
- Symptôme : déluge de notifications.
- Cause : fenêtres
for:trop courtes, requêtes bruyantes, agrégations manquantes. - Correctif : relever les seuils, allonger
for:, dédupliquer dans Alertmanager et grouper par labels.
- Alertes mémoire non actionnables
- Symptôme : alerte mémoire alors qu'aucune limite n'est définie.
- Cause : conteneurs sans limites rapportent une spec illimitée ; les ratios perdent leur sens.
- Correctif : utiliser des seuils absolus par hôte ou imposer des limites avec
docker update --memorysi pertinent.
- Effets de bord du redémarrage Docker
- Symptôme : brèves perturbations du plan de contrôle.
- Cause : redémarrage du démon.
- Correctif : planifier une fenêtre ; vérifier après redémarrage que
docker psetdocker pullfonctionnent.
Retour arrière et récupération
- Revenir à la configuration Docker précédente
sudo cp -a /etc/docker/daemon.json.bak.* /etc/docker/daemon.jsonsudo systemctl restart docker- Vérifier :
docker psetcurl 127.0.0.1:9323/metrics(l'échec est attendu si vous avez retiré les métriques)
- Désactiver rapidement les composants de monitoring
- Stopper cAdvisor :
docker rm -f cadvisor - Stopper Prometheus :
docker rm -f prometheus - Stopper Alertmanager :
docker rm -f alertmanager
- Réduire temporairement le bruit d'alerte
- Créer un silence dans Alertmanager sur
severity=warningou un nom d'alerte précis. - Augmenter
for:dansalerts.yml(ex. 5m -> 15m) pour les alertes non critiques et recharger Prometheus (redémarrer le conteneur).
- Récupérer de l'espace disque si les logs dérapent
- Confirmer le log driver et la rotation :
docker info | grep -i 'Logging Driver' -A2 - Avec
json-file, s'assurer quemax-sizeetmax-filesont définis ; mettre à jour daemon.json et redémarrer Docker.
Checklist d'exploitation
- Capacité et base
- Revoir le top 5 des conteneurs par CPU et mémoire sur 7 jours.
- Confirmer qu'aucun conteneur ne tourne sans limite mémoire si vous utilisez des alertes en ratio.
- Vérifier l'espace disque sur
/var/lib/docker:df -h /var/lib/docker.
- Signaux et alertes
- S'assurer que les cibles Prometheus sont UP.
- Revoir l'historique d'alertes et éliminer le bruit persistant (seuils, fenêtres
for:). - Confirmer qu'au moins une alerte de test atteint votre canal.
- Logs et événements
- Repérer les redémarrages fréquents :
docker ps --format '{{.Names}} {{.Status}}' | grep -E 'Up|Restarting'. - Échantillonner les événements engine :
docker events --since 24h --filter type=container --filter event=oom --filter event=die | head -n 20.
- Workflow de réponse aux incidents (dans l'ordre)
- Identifier le conteneur le plus bruyant via le contexte d'alerte.
- Inspecter vite l'état :
docker inspect -f '{{.Name}} State={{.State.Status}} OOM={{.State.OOMKilled}} Restarts={{.RestartCount}}' <container>. - Récupérer les logs autour de l'heure de panne :
docker logs --since 10m <container>. - En cas de dérapage CPU, envisager un cap temporaire :
docker update --cpus 1.0 <container>(vérifiez l'impact avant). - En crash loop, désactiver
--restartou mettre à l'échelle à 0 le temps du triage :docker update --restart=no <container>ou recréer sans restart. - Documenter la cause racine et la prévention (limite, correctif code, probes) avant de réactiver l'auto-restart.
Tableaux de bord pratiques (requêtes prêtes à coller)
- CPU :
topk(10, rate(container_cpu_usage_seconds_total{container!=""}[5m])) - Working set mémoire :
topk(10, container_memory_working_set_bytes{container!=""}) - Redémarrages :
sum by (container) (changes(container_start_time_seconds{container!=""}[1h])) - Événements OOM :
increase(container_oom_events_total{container!=""}[1h])
À étendre après que le pilote soit calme
- Ajouter des collecteurs au niveau nœud (filesystem, réseau) et des alertes pour la pression disque et l'épuisement des inodes.
- Introduire des tableaux de bord sur la dérive d'image et de tag pour repérer les upgrades inattendus.
- Sécuriser les métriques avec TLS ou isoler les scrapers sur un réseau de monitoring au-delà de localhost.
- Intégrer Alertmanager avec vos canaux (chat, ticketing, astreinte) et router par service ou équipe.
Conclusion
Vous disposez désormais d'une base vérifiable pour la surveillance Docker et les Docker alerts : métriques engine et conteneur collectées localement, règles d'alerte actionnables pour CPU, mémoire, redémarrages et OOM kills, et une checklist qui rend les opérations répétables. Parce que le pilote est étroit et inspectable en local, il est simple d'ajuster les seuils, de valider le routage et de revenir en arrière si besoin. Une fois vos alertes calmes, spécifiques et fiables, étendez la couverture aux ressources des nœuds, aux dashboards par équipe et à un routage d'alerte de niveau production pour une meilleure Docker incident response.