4.2Fiabiliser : healthcheck et restart policies
L'essentiel en 30 secondes
- restart ressuscite, healthcheck prouve : la politique de redémarrage relance le conteneur après crash ou reboot ; le test de santé périodique dit si le service est vraiment prêt (pas seulement lancé).
- depends_on ordonne, condition: service_healthy attend le vrai prêt : sans condition, l'ordre de démarrage n'est qu'un espoir — avec un healthcheck sur la base, l'API ne démarre que sur du prouvé sain.
- Réflexe d'Idir : unless-stopped par défaut (respecte les arrêts volontaires), et Up n'est pas healthy : un service Up mais unhealthy est un malade à soigner, pas un service qui tourne.
Mini-cas filé — Idir en finit avec les crashs du lundi matin
Idir, devops junior à Alger, se fait réveiller : après une coupure électrique, l'API est démarrée mais la base n'était pas prête — crashs en cascade. Il ajoute restart: unless-stopped à chaque service durable, un healthcheck pg_isready sur la base, et fait dépendre l'API de service_healthy. Il tue ensuite la base pour vérifier : relance automatique et attente prouvée. Deuxième jalon du fil rouge : la stack redémarre seule et ne route que vers du prouvé sain.
Suite du cas 4.1 — l'image publiée par Idir tourne maintenant de façon autonome.
1. restart : la politique de résurrection
restart: unless-stopped relance le conteneur après un crash ou un reboot machine, sauf arrêt volontaire — le bon défaut pour un service durable. always relance même après un stop manuel (réservé aux services critiques), on-failure ne relance qu'en cas d'erreur. Sans politique, comme avant le correctif d'Idir, un crash nocturne attend le matin.
Choisir selon l'intention : durable (unless-stopped), critique qui ne doit jamais s'arrêter (always), tâche qui ne doit repartir qu'en échec (on-failure). Et on évite always partout : il redémarre même vos arrêts volontaires.
2. healthcheck : « prêt » vaut mieux que « lancé »
depends_on ordonne, healthcheck prouve : une commande testée périodiquement (pg_isready pour Postgres, une requête HTTP pour une API) passe le service à healthy. On peut alors attendre le vrai prêt (condition: service_healthy) au lieu d'espérer que la base ait fini de démarrer.
Le test doit viser le vrai service (une requête, pas la simple présence du processus) : c'est ce qui fait disparaître les crashs de démarrage « base pas prête » d'Idir.
3. Trois états, trois réactions
starting (on attend), healthy (on route), unhealthy (on alerte, on n'envoie plus de trafic). docker compose ps affiche l'état : un service Up mais unhealthy est un malade à soigner (logs, diagnostic), pas un service qui tourne.
Régler la fréquence avec mesure : assez souvent pour détecter (10 à 30 secondes), avec des essais répétés pour éviter les faux positifs. Un test trop agressif passe son temps à signaler ; trop rare, il rate les pannes.
Le savais-tu ?
Up, c'est le pouls ; healthy, c'est la forme.
🔎 Exemple concret — 🔎 Exemple concret — Postgres qui prouve sa santé
La stack d'Idir : l'API ne démarre que sur base prouvée prête.
services:
bdd:
image: postgres:16.4
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
retries: 5
api:
build: ./api
depends_on:
bdd:
condition: service_healthy
Lecture : l'API ne démarre que sur base prouvée prête.
Leçon : les crashs de démarrage « base pas prête » disparaissent.
Vocabulaire de la section
- restart
- Politique de relance automatique du conteneur : no, on-failure, always, unless-stopped.
Exemple simple : Idir met unless-stopped : relance après crash ou reboot, mais respecte son stop manuel.
Ce que ce n'est pas : un redémarrage manuel à 3 h du matin après chaque crash.
Réflexe : service durable : déclarer une politique restart.
- healthcheck
- Test périodique qui prouve la SANTÉ RÉELLE du service (requête, pas simple processus).
Exemple simple : pg_isready prouve que la base d'Idir accepte vraiment les connexions.
Ce que ce n'est pas : un simple ordre de démarrage sans vérification.
Réflexe : dépendance critique : tester le vrai service.
- healthy / unhealthy
- État sain ou malade selon le dernier test de santé — indépendant du fait que le processus tourne.
Exemple simple : La base d'Idir est Up mais unhealthy : il diagnostique au lieu de router.
Ce que ce n'est pas : un simple marche ou arrêt.
Réflexe : Up + unhealthy : soigner, pas router.
- condition: service_healthy
- Dans depends_on : attendre que la dépendance soit prouvée saine avant de démarrer.
Exemple simple : L'API d'Idir attend la base healthy au lieu d'espérer.
Ce que ce n'est pas : un ordre de lancement sans garantie de disponibilité.
Réflexe : démarrage ordonné : exiger la condition, pas seulement l'ordre.
En pratique — En pratique — Rendre votre stack autonome
- Ajoutez restart: unless-stopped à chaque service durable.
- Ajoutez un healthcheck à la base (pg_isready).
- Faites dépendre l'API de service_healthy.
- Tuez la base (kill) : observez relance + attente prouvée.
Script prêt à dire — expliquer la fiabilisation à l'équipe (30 s)
« C'est Idir : chaque service durable redémarre seul après un crash, la base prouve qu'elle est prête avec un test réel, et l'API attend cette preuve avant de démarrer. Fini les réveils après une coupure : la stack se relève seule. »
À dire en revue : montrez le test kill de la base devant l'équipe.
Modèle copier-coller — base prouvée + API qui attend (Compose)
services:
bdd:
image: postgres:16.4
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
timeout: 5s
retries: 5
api:
build: ./api
restart: unless-stopped
depends_on:
bdd:
condition: service_healthy
API web à tester en HTTP
Comme Idir mais avec un test de requête web sur la page d'accueil : le service est healthy quand il répond vraiment.
Service critique 24/7
restart: always assumé et documenté : même un stop manuel relance — à réserver aux cas vraiment critiques.
Tâche ponctuelle
restart: on-failure : on ne relance qu'en cas d'erreur, pas après un succès normal.
Faux sentiment de sécurité
depends_on sans condition + test qui vise le mauvais conteneur : à corriger vers service_healthy et test réel.
✓ Bonnes pratiques
- unless-stopped par défaut en durable.
- Tester le vrai service (requête, pas le PID).
- Lire l'état health dans compose ps.
✗ Pièges fréquents
- always partout (redémarre même vos stops).
- depends_on sans condition (faux sentiment).
- Healthcheck qui teste le mauvais conteneur.
Points clés à retenir
- restart ressuscite, healthcheck prouve.
- depends_on + condition = vrai ordre.
- Up n'est pas healthy.
- unless-stopped : le bon défaut.
Défi 48h — appliquez demain
Sur votre vraie stack : ajoutez unless-stopped + healthcheck + condition, tuez la base et observez relance et attente prouvée.
- Je sais déclarer une politique restart adaptée.
- Je sais écrire un healthcheck qui prouve le vrai prêt.
- Je sais faire attendre service_healthy et lire l'état.
Questions fréquentes
Healthcheck ou simple nouvel essai dans l'appli ?
Les deux : les nouveaux essais rendent l'appli robuste partout, le healthcheck rend la stack observable et ordonnançable. Ce sont des alliés, pas des concurrents.
Quelle fréquence de test ?
Assez souvent pour détecter (10 à 30 secondes), avec des essais répétés pour éviter les faux positifs. Un test trop agressif signale sans arrêt ; trop rare, il rate les pannes.
Un service est « Up (unhealthy) ». Que faut-il comprendre ?