Chapitre 1013 minIntermédiaire
Journaux et supervision des conteneurs
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- choisir un pilote de journalisation et régler la rotation ;
- centraliser les journaux des conteneurs vers un serveur syslog ;
- superviser des conteneurs avec le modèle Docker de Zabbix ;
- repérer les événements Docker suspects avec Wazuh.
4 exercices corrigés
Superviser des conteneurs, c'est collecter leurs journaux (ce qu'ils écrivent sur leur sortie standard), surveiller leur état et leur santé, et mesurer leur consommation de processeur, de mémoire et de disque, pour être alerté avant que les utilisateurs ne le soient. Ce chapitre règle la journalisation de Docker (pilotes, rotation, centralisation vers le serveur de journaux), puis branche srv-gestion sur Zabbix et Grafana pour les métriques et les alertes, et sur Wazuh pour les événements de sécurité.
Où vont les journaux d'un conteneur
Une application conteneurisée écrit ses journaux sur sa sortie standard et sa sortie d'erreur, pas dans des fichiers. Le démon les capture et les confie à un pilote de journalisation (logging driver). docker logs et docker compose logs les relisent :
docker compose logs --tail 100 -t api # 100 dernières lignes, avec l'horodatage de Docker
docker compose logs -f --since 15m # tous les services, en continu, depuis 15 minutes
| Pilote | Où vont les journaux | docker logs |
|---|---|---|
json-file (par défaut) | Un fichier JSON par conteneur, sous /var/lib/docker/containers/, sans rotation par défaut | Oui |
local | Un format binaire compact, avec rotation et compression | Oui |
journald | Le journal de systemd de l'hôte | Oui, et journalctl CONTAINER_NAME=gestion-api-1 |
syslog | Un serveur syslog, local ou distant | Oui, grâce au cache local de Docker |
gelf, fluentd | Graylog, Fluentd et outils compatibles | Oui, grâce au cache local |
none | Nulle part | Non |
Le pilote peut aussi se régler service par service dans compose.yaml :
services:
api:
logging:
driver: local
options:
max-size: "20m"
max-file: "5"
Centraliser les journaux vers srv-journaux
Des journaux qui restent sur srv-gestion disparaissent avec lui, et un attaquant qui prend la main sur le serveur peut les effacer. Chez Sorbier, tous les serveurs envoient leurs journaux à srv-journaux (192.168.10.180), en syslog chiffré par TLS sur le port TCP 6514, la même règle que pour le serveur web de la DMZ (cours Cybersécurité des infrastructures). Deux façons de faire :
1. Le pilote journald, et l'envoi par l'hôte. Les conteneurs écrivent dans le journal de systemd de srv-gestion, et le service rsyslog de l'hôte, déjà configuré pour transmettre ses journaux à srv-journaux, transmet aussi ceux des conteneurs. Dans daemon.json :
{
"log-driver": "journald",
"log-opts": {
"tag": "{{.Name}}"
}
}
Si srv-journaux est injoignable, rien ne se perd : les journaux attendent dans le journal local, et les conteneurs ne sont pas gênés.
2. Le pilote syslog, directement depuis Docker, service par service :
services:
proxy:
logging:
driver: syslog
options:
syslog-address: "tcp+tls://192.168.10.180:6514"
syslog-tls-ca-cert: "/etc/ssl/certs/sorbier-ca.pem"
syslog-format: "rfc5424"
tag: "{{.Name}}"
Plus direct, mais plus fragile : par défaut, si le serveur syslog est injoignable au démarrage, le conteneur ne démarre pas.
Surveiller l'état et la santé
Un conteneur peut être en marche sans que son service fonctionne. Trois signaux à surveiller :
| Signal | Où le lire | Ce qu'il révèle |
|---|---|---|
L'état (running, exited, restarting) | docker ps -a, docker inspect -f '{{.State.Status}}' | Un service arrêté ou qui redémarre en boucle |
La santé (healthy, unhealthy) | docker ps, docker inspect -f '{{.State.Health.Status}}' | Un service lancé mais qui ne répond plus |
| Le nombre de redémarrages | docker inspect -f '{{.RestartCount}}' | Un service qui plante et repart, masqué par restart: unless-stopped |
Le flux d'événements du démon montre tout ce qui arrive, en direct :
docker events --filter event=die --filter event=health_status --filter event=oom
2026-11-03T14:02:11.508+01:00 container health_status: unhealthy 8b1e… (image=ghcr.io/sorbier/sorbier-frais:2.5.0, name=gestion-api-1)
2026-11-03T14:02:41.932+01:00 container die 8b1e… (exitCode=1, image=ghcr.io/sorbier/sorbier-frais:2.5.0, name=gestion-api-1)
Les métriques : docker stats et au-delà
docker stats donne la consommation instantanée de chaque conteneur (chapitre 3). Pour garder un historique, tracer des courbes et être alerté, on branche l'hôte sur l'outil de supervision de l'entreprise. Ce qu'il faut surveiller sur un hôte Docker :
| Mesure | Seuil d'alerte typique | Pourquoi |
|---|---|---|
Espace libre de /var/lib/docker | Moins de 20 % | Images, journaux et volumes remplissent le disque |
| Mémoire d'un conteneur par rapport à sa limite | Plus de 90 % | Au-delà, le noyau tue le processus (code 137, OOMKilled) |
| Conteneurs arrêtés qui devraient tourner | Un seul | Service indisponible |
Conteneurs unhealthy | Un seul | Service qui ne répond plus |
| Redémarrages par heure | Plus de quelques-uns | Application qui plante en boucle |
| Date d'expiration du certificat publié | Moins de 21 jours | Site inaccessible le jour de l'expiration |
Superviser Docker avec Zabbix et Grafana
Chez Sorbier, les métriques et les alertes sont dans Zabbix, et les tableaux de bord dans Grafana, branché sur Zabbix (cours Supervision). Zabbix fournit un modèle prêt à l'emploi, « Docker by Zabbix agent 2 » : l'agent 2, installé sur srv-gestion, interroge l'API du démon par son socket et découvre automatiquement chaque conteneur (état, processeur, mémoire, réseau, redémarrages), avec des déclencheurs prêts à l'emploi.
-
Sur srv-gestion, installe l'agent 2 depuis le dépôt de Zabbix et déclare le serveur Zabbix dans
/etc/zabbix/zabbix_agent2.conf(Server=etServerActive=). -
Donne à l'agent l'accès au socket. La documentation propose d'ajouter l'utilisateur
zabbixau groupedocker, puis de redémarrer l'agent :sudo usermod -aG docker zabbix sudo systemctl restart zabbix-agent2 -
Dans l'interface de Zabbix, menu Data collection > Hosts, ouvre l'hôte
srv-gestionet ajoute le modèle « Docker by Zabbix agent 2 » à côté de « Linux by Zabbix agent ». -
Vérifie la remontée dans Monitoring > Latest data, filtré sur l'hôte.
Complète la supervision de l'hôte par celle du service rendu : un scénario web Zabbix qui ouvre https://gestion.ad.sorbier.example/api/health toutes les minutes vérifie, du point de vue des utilisateurs, que la chaîne complète (DNS, pare-feu, proxy, API, base) fonctionne. L'expiration du certificat se surveille avec le modèle « Website certificate by Zabbix agent 2 » : sur l'hôte srv-gestion, la macro {$CERT.WEBSITE.HOSTNAME} reçoit le nom gestion.ad.sorbier.example, et la macro {$CERT.EXPIRY.WARN} (7 jours par défaut) passe à 21 jours, pour avoir le temps de faire signer un nouveau certificat.
Les événements de sécurité avec Wazuh
La supervision dit si le service fonctionne ; la détection dit si quelqu'un fait quelque chose d'anormal. L'agent Wazuh installé sur srv-gestion peut écouter les événements de Docker grâce à son module Docker listener : chaque pull, création, démarrage, arrêt et chaque docker exec dans un conteneur remonte au serveur Wazuh. On l'active dans /var/ossec/etc/ossec.conf de l'agent :
<wodle name="docker-listener">
<disabled>no</disabled>
</wodle>
Le module est écrit en Python et demande la bibliothèque Python docker sur l'hôte, dans la version indiquée par la documentation de ta version de Wazuh. Ce qu'on cherche à repérer :
- un
docker execdans un conteneur de production en dehors d'une intervention planifiée ; - la création d'un conteneur privilégié, ou qui monte la racine de l'hôte ou le socket Docker ;
- une image inconnue téléchargée sur le serveur ;
- un conteneur qui redémarre en boucle (souvent le signe d'un problème, parfois d'une attaque).
La collecte des journaux de sécurité et la corrélation des alertes sont traitées dans le cours Cybersécurité des infrastructures.
Exercices
Exercice 1 sur 4 Le disque plein Réussi À revoir
Un lundi matin, plus aucun conteneur de srv-gestion n'arrive à écrire, et df -h montre /var/lib/docker plein à 100 %. sudo du -sh /var/lib/docker/containers/* montre un dossier de 38 Go. Explique la cause probable, rétablis le service et évite que cela se reproduise.
Voir la réponseMasquer la réponse de l'exercice 1
Cause probable : un conteneur bavard (souvent en boucle d'erreur) dont les journaux, avec le pilote json-file sans rotation, ont grossi jusqu'à remplir le disque. Le dossier de 38 Go est celui de ce conteneur ; son fichier *-json.log contient les journaux.
Rétablir :
- identifier le conteneur (le nom du dossier est son identifiant :
docker ps -a --no-trunc | grep <début de l'identifiant>) et lire la fin de ses journaux pour comprendre l'erreur ; - libérer l'espace : recréer le conteneur (
docker compose up -d --force-recreate <service>), ce qui supprime l'ancien fichier, ou à défaut le vider avecsudo truncate -s 0sur le fichier*-json.log; - corriger l'erreur de l'application qui produisait les journaux en boucle.
Éviter : rotation dans /etc/docker/daemon.json ("log-driver": "local" ou json-file avec max-size et max-file), puis recréer tous les conteneurs pour qu'ils l'appliquent ; alerte de supervision quand l'espace libre de /var/lib/docker passe sous 20 %.
Tu avais trouvé ?
Exercice 2 sur 4 Choisir la centralisation Réussi À revoir
Le technicien hésite entre le pilote syslog vers srv-journaux et le pilote journald avec envoi par rsyslog. Srv-journaux est redémarré chaque mois pour ses mises à jour. Que conseilles-tu ?
Voir la réponseMasquer la réponse de l'exercice 2
Le pilote journald avec envoi par rsyslog depuis l'hôte. Pendant le redémarrage mensuel de srv-journaux, les journaux restent dans le journal local de srv-gestion et rsyslog les renvoie quand le serveur revient. Avec le pilote syslog direct, un conteneur créé ou redémarré pendant cette fenêtre ne démarrerait pas (le pilote ne peut pas joindre le serveur), ce qui transformerait une maintenance du serveur de journaux en panne des applications.
Tu avais trouvé ?
Exercice 3 sur 4 Interpréter des événements Réussi À revoir
docker events a enregistré cette nuit, sur srv-gestion, la séquence suivante (simplifiée). Que s'est-il probablement passé, et que fais-tu ?
02:14:07 image pull alpine:3.24
02:14:09 container create (image=alpine:3.24, name=maintenance)
02:14:09 container start (name=maintenance)
02:14:40 container die (exitCode=0, name=maintenance)
02:14:41 container destroy (name=maintenance)
Aucune intervention n'était planifiée, et docker inspect n'est plus possible puisque le conteneur a été détruit.
Voir la réponseMasquer la réponse de l'exercice 3
Quelqu'un (ou un programme) qui a accès au démon Docker a téléchargé une image, lancé un conteneur jetable pendant une trentaine de secondes, puis l'a supprimé, en pleine nuit et sans intervention prévue. Avec l'accès au socket, un tel conteneur peut monter la racine de l'hôte et y modifier n'importe quoi (ajouter une clé SSH, un compte, une tâche planifiée) : c'est le schéma d'une prise de contrôle de l'hôte.
À faire : traiter comme un incident de sécurité. Prévenir le responsable ; ne pas éteindre le serveur à la légère (les traces en mémoire seraient perdues) ; rechercher qui avait accès au démon à cette heure (journaux d'authentification SSH, membres du groupe docker, jetons d'accès de la CI) ; vérifier les modifications récentes sur l'hôte (/root/.ssh/authorized_keys, /etc/passwd, tâches planifiées, services systemd) ; conserver les journaux de srv-journaux et de Wazuh comme preuves. La conduite à tenir est détaillée dans le cours Réponse à incident.
Tu avais trouvé ?
Exercice 4 sur 4 Les alertes à créer Réussi À revoir
Antoine Mercier te demande la liste des alertes à configurer dans Zabbix pour l'application sorbier-frais. Propose-en cinq, avec leur seuil et leur sévérité.
Voir la réponseMasquer la réponse de l'exercice 4
| Alerte | Seuil | Sévérité |
|---|---|---|
Scénario web https://gestion.ad.sorbier.example/api/health en échec | 3 échecs consécutifs (3 minutes) | Haute : le service est indisponible pour les utilisateurs |
Conteneur gestion-api-1 ou gestion-bdd-1 arrêté | Dès qu'il n'est plus running | Haute |
| Conteneur redémarré plusieurs fois | Plus de 3 redémarrages en une heure | Moyenne : l'application plante, même si elle repart |
Espace libre de /var/lib/docker | Moins de 20 % (moyenne), moins de 10 % (haute) | Moyenne puis haute |
Expiration du certificat de gestion.ad.sorbier.example | Moins de 21 jours | Moyenne : le temps de faire signer un nouveau certificat |
D'autres réponses sont possibles : mémoire de l'API proche de sa limite, export nocturne de la base absent, conteneur unhealthy.
Tu avais trouvé ?