Lab 8.1 : Superviser une pile applicative¶
| Durée | 75 min |
| Niveau | Semi-guidé |
| Prérequis | Lab 7.2 : Application trois niveaux avec Compose (dossier tp-trois-niveaux), cours du chapitre 8 |
| Acquis visés | AA6 |
Objectifs
- Consulter et filtrer les journaux d'une pile
- Mesurer la consommation de ressources et fixer des limites
- Suivre l'activité du moteur avec
docker events - Lire l'état de santé des services
- Provoquer et reconnaître un arrêt par manque de mémoire
- Mesurer l'espace occupé par Docker et nettoyer prudemment
Contexte et schéma¶
Vous supervisez la pile du Lab 7.2 (proxy, API, base de données). Chaque étape utilise un outil d'observation différent ; vous terminez par une fiche qui associe chaque question d'exploitation à la bonne commande. Dans ce lab, seules les commandes clés vous sont données : à vous de les adapter et de déduire le reste à l'aide du cours.
flowchart LR
subgraph PILE["Pile tp-trois-niveaux"]
P["proxy"]
A["api"]
D["db"]
end
PILE --> L["docker logs<br/>journaux"]
PILE --> S["docker stats<br/>consommation"]
PILE --> E["docker events<br/>activité du moteur"]
PILE --> I["docker inspect<br/>état et santé"]
Selon votre option
- Sous PowerShell, utilisez
curl.exeet écrivez les commandes sur une seule ligne. Pour générer du trafic, utilisez1..30 | ForEach-Object { curl.exe -s http://localhost:8080 | Out-Null }. - Avec Docker Desktop, les mesures de
docker statsportent sur la machine virtuelle interne ; les valeurs diffèrent de celles d'une machine Linux. - Ouvrez deux terminaux pour l'étape 5.
Étapes¶
Étape 1 : Démarrer la pile et relever un état de référence¶
- Objectif : partir d'une pile saine, dont vous connaissez l'état normal.
- Indices :
- Placez-vous dans
tp-trois-niveaux(recréez le dossier à partir du Lab 7.2 si besoin), puisdocker compose up -d --build. - Attendez que
dbetapisoienthealthy(docker compose ps), puis testezcurl http://localhost:8080.
- Placez-vous dans
Point de contrôle
- Les trois services sont
running,dbetapisonthealthy -
curlrenvoieNombre de visites : ...
Étape 2 : Interroger les journaux¶
- Objectif : retrouver une information précise dans les journaux.
- Indices :
- Générez du trafic : une trentaine de requêtes
curlvershttp://localhost:8080. - Affichez les 10 dernières lignes des journaux du
proxy, puis de l'api, avec horodatage (--tail,-t). - Affichez uniquement les journaux de la dernière minute (
--since 1m). - Suivez en continu les journaux de toute la pile (
docker compose logs -f), envoyez une requêtecurldepuis un autre terminal, et repérez la ligne correspondante dans chaque service.
- Générez du trafic : une trentaine de requêtes
Point de contrôle
- Vous avez repéré, dans les journaux du
proxy, la ligne correspondant à votre dernière requête - Vous avez repéré la même requête dans les journaux de l'
api - Vous savez expliquer pourquoi les journaux de
dbne contiennent pas de ligne par requête HTTP
Étape 3 : Mesurer la consommation¶
- Objectif : connaître la consommation normale de chaque service.
- Indices :
docker stats --no-stream: relevez, pour chaque conteneur,CPU %,MEM USAGE / LIMITetPIDS.- Lancez
docker statsen continu dans un terminal pendant que vous générez du trafic dans un autre : quelle colonne varie ? docker compose top(oudocker top <conteneur>) liste les processus.
Point de contrôle
- Vous avez relevé la mémoire utilisée par
proxy,apietdb - Pour chaque conteneur, la limite affichée correspond à la mémoire totale de la machine (aucune limite fixée)
- Vous avez identifié le service qui consomme le plus de mémoire
Étape 4 : Fixer des limites de ressources¶
- Objectif : limiter les services d'après les mesures de l'étape 3.
- Indices :
- Dans
compose.yaml, ajoutez au serviceapiles clésmem_limit(par exemple128m) etcpus(par exemple0.5), puismem_limit(par exemple256m) au servicedb(section 6 du cours). - Vérifiez avec
docker compose config, puis appliquez avecdocker compose up -d. - Si le proxy ne répond plus après la recréation de
api, redémarrez-le (docker compose restart proxy). - Contrôlez avec
docker stats --no-streamet refaites quelques requêtes.
- Dans
Point de contrôle
- La colonne
MEM USAGE / LIMITaffiche 128 Mo pourapiet 256 Mo pourdb - L'application répond toujours normalement
- Vous pouvez justifier le choix des limites par vos mesures de l'étape 3
Étape 5 : Suivre les événements du moteur¶
- Objectif : voir ce que fait Docker quand un service s'arrête et redémarre.
- Indices :
- Terminal 1 :
docker events --filter type=container. - Terminal 2 :
docker compose restart api, puisdocker compose stop dbetdocker compose start db. - Relevez les événements
die,stop,startethealth_status. - Avec un seul terminal, lancez d'abord les actions, puis consultez
docker events --since 5m --until 0s --filter type=container(à la place du suivi en continu).
- Terminal 1 :
Point de contrôle
- Vous avez observé l'enchaînement d'événements d'un redémarrage (
kill/die/stop, puisstart) - Vous avez observé au moins un événement
health_status - Vous savez dire quel service a été touché par chaque événement (attribut
name)
Étape 6 : Lire l'état de santé¶
- Objectif : exploiter le healthcheck pour connaître l'état réel des services.
- Indices :
docker compose ps: relevez l'état de santé affiché.- Affichez le détail des vérifications de l'
api:
- Vérifiez le nom exact du conteneur avec `docker ps` ; il dépend du nom du projet.
- Arrêtez `db` (`docker compose stop db`), attendez une vingtaine de secondes, puis relevez de nouveau l'état de `api` et celui du site (`curl`). Redémarrez `db`.
Point de contrôle
- Vous avez lu le champ
Statuset le journal des dernières vérifications (Log) de l'api - Pendant l'arrêt de
db, l'apirestehealthyalors que le site renvoie une erreur - Vous pouvez expliquer cet écart (voir les questions de réflexion)
Étape 7 : Provoquer et reconnaître un arrêt par manque de mémoire¶
- Objectif : voir un OOM kill et savoir l'identifier a posteriori.
- Indices :
- Lancez un conteneur
gourmand(alpine:3.20) limité à 32 Mo, sans mémoire d'échange supplémentaire (--memory 32m --memory-swap 32m), qui exécute la commandetail /dev/zero(elle lit un flux sans fin sans saut de ligne et remplit la mémoire). - Une fois le conteneur arrêté, relevez :
docker ps -a, le code de sortie, et l'indicateurOOMKilled(section 5.2 du cours). - Retrouvez l'événement
oomavecdocker events --since 5m --until 0s --filter event=oom.
- Lancez un conteneur
Point de contrôle
- Le conteneur est à l'état
Exited (137) -
OOMKilledvauttrue - L'événement
oomapparaît dans la liste des événements
Étape 8 : Mesurer et nettoyer¶
- Objectif : récupérer de l'espace sans supprimer de données utiles.
- Indices :
docker system df: notez l'espace occupé et l'espace récupérable pour chaque type de ressource.- Listez ce qui serait supprimé :
docker ps -a(conteneurs arrêtés),docker images,docker volume ls. - Supprimez les conteneurs arrêtés avec
docker container prune. Lisez le message de confirmation avant de valider. - Supprimez les images sans nom avec
docker image prune. - N'exécutez pas
docker volume prunenidocker system prune --volumes: vos volumes contiennent des données. - Relancez
docker system dfet comparez.
Point de contrôle
- Le conteneur
gourmanda disparu, la pile est intacte - Vous avez comparé l'espace avant et après nettoyage
- Vous savez expliquer pourquoi vous n'avez pas nettoyé les volumes
Étape 9 (facultative) : Limiter la taille des journaux¶
- Objectif : éviter qu'un conteneur très bavard sature le disque.
- Indices :
- Lancez un conteneur
bavard(alpine:3.20) qui écrit une ligne par seconde, avec--log-opt max-size=10m --log-opt max-file=3(section 2.2 du cours). - Vérifiez la configuration avec
docker inspect -f '{{.HostConfig.LogConfig}}' bavard.
- Lancez un conteneur
Point de contrôle
-
docker inspectaffiche les optionsmax-sizeetmax-file
Étape 10 : Dresser votre fiche d'exploitation¶
- Objectif : associer chaque question d'exploitation à la bonne commande.
- Indices : complétez le tableau avec la commande exacte que vous utiliseriez, en vous appuyant sur ce que vous venez de faire.
| Question | Commande |
|---|---|
| Que dit l'application depuis 10 minutes ? | |
| Combien de mémoire consomme chaque service maintenant ? | |
| Pourquoi ce conteneur s'est-il arrêté ? (deux commandes) | |
| Quels événements sont survenus dans les 30 dernières minutes ? | |
| Le service est-il en bonne santé ? | |
| Combien d'espace Docker occupe-t-il sur le disque ? |
Point de contrôle
- Chaque ligne contient une commande que vous avez effectivement exécutée pendant ce lab
Questions de réflexion¶
Pourquoi la limite de mémoire d'un conteneur sans option --memory correspond-elle à la mémoire de la machine ?
Sans limite, le conteneur peut utiliser toute la mémoire disponible sur l'hôte (ou dans la machine virtuelle de Docker Desktop). La colonne LIMIT affiche donc la mémoire totale.
Pourquoi l'API reste-t-elle healthy quand la base est arrêtée, alors que le site renvoie une erreur ?
Son healthcheck interroge la route /sante, qui ne touche pas à la base : il vérifie que le processus de l'API répond, pas que ses dépendances fonctionnent. L'état de santé mesure ce que le healthcheck teste, rien de plus.
Quelle information le code de sortie 137 seul ne donne-t-il pas, et comment l'obtenir ?
Il indique un processus tué par le signal 9, sans dire pourquoi : arrêt forcé ou manque de mémoire. L'indicateur OOMKilled de docker inspect, ou l'événement oom, confirme la cause.
Pourquoi docker volume prune est-il plus risqué que docker container prune ?
Un conteneur arrêté se recrée à partir de l'image. Un volume contient des données qui n'existent nulle part ailleurs : leur suppression est irréversible.
Dépannage¶
| Symptôme | Pistes |
|---|---|
Error: No such container avec docker inspect |
Le nom du conteneur dépend du nom du projet : vérifiez-le avec docker ps |
docker events n'affiche rien |
Lancez-le avant les actions, ou utilisez --since et --until 0s pour relire les événements passés |
docker stats n'affiche rien pour un conteneur |
Seuls les conteneurs en cours d'exécution sont mesurés |
curl ne répond plus après le changement des limites |
api a été recréée : redémarrez le proxy (docker compose restart proxy) |
gourmand ne s'arrête pas |
La limite est peut-être mal appliquée : vérifiez --memory et --memory-swap, et utilisez une limite plus basse (16 Mo) |
OOMKilled reste à false avec un code 137 |
L'arrêt vient d'un autre signal : consultez les événements et relancez avec une limite plus basse |
mem_limit ou cpus refusés par docker compose config |
Vérifiez l'indentation : ces clés sont au niveau du service |
Sous PowerShell, les accolades de -f sont mal interprétées |
Écrivez la commande sur une seule ligne, avec le modèle entre apostrophes |
Nettoyage et reprise¶
Les conteneurs gourmand et bavard n'existent peut-être plus : Docker le signale sans conséquence. Conservez le dossier tp-trois-niveaux. Le Lab 8.2 fournit sa propre pile à dépanner.
Retour au chapitre¶
Chapitre 8 : Observabilité et dépannage · Lab suivant : Lab 8.2 : Dépanner des pannes imposées