4.2 · Fiabiliser : healthcheck et restart policies

Niveau 4 · Registres, fiabilité & CI

4.2Fiabiliser : healthcheck et restart policies

Objectif : Rendre un service capable de redémarrer seul et de signaler son état réel.
Temps estimé : 12 min · lecture autonome · Si vous n'avez que 5 min : lisez « L'essentiel en 30s » + le schéma.

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.

Erreur d'interprétation fréquente : « depends_on suffit à ordonner le démarrage, et always partout c'est plus sûr ». Non. Sans condition service_healthy, depends_on ne fait qu'ordonner le lancement sans attendre que la base soit prête — les crashs « base pas prête » reviennent ; et always partout redémarre même vos arrêts volontaires de maintenance. unless-stopped par défaut, healthcheck qui prouve, condition qui attend : c'est ce trio qui fiabilise.
Rendre un service autonome Relance auto, santé prouvée, trafic vers le sain Politique restart Relanceaprès crash ou rebootTest healthcheck Prouvele vrai prêtDépendance conditionnelle Attendservice_healthyLecture de l'état Upn'est pas healthy
Relance auto, santé prouvée, trafic vers le sain
Version texte du schéma (SEO / lecteurs d'écran / traduction) : 1) Idir ajoute restart: unless-stopped à chaque service durable pour survivre aux crashs et aux reboots. 2) Il ajoute un healthcheck pg_isready sur la base qui prouve le vrai prêt. 3) Il fait dépendre l'API de service_healthy au lieu d'un simple ordre de démarrage. 4) Il lit docker compose ps : Up mais unhealthy veut dire diagnostiquer, pas router. Leçon : restart ressuscite, healthcheck prouve, la condition attend le vrai prêt.

Le savais-tu ?

Un conteneur peut afficher Up depuis des heures alors que son application ne répond plus à personne — le processus vit, le service est mort.
Vrai : Up décrit le processus, healthy décrit le service. D'où le healthcheck.

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

  1. Ajoutez restart: unless-stopped à chaque service durable.
  2. Ajoutez un healthcheck à la base (pg_isready).
  3. Faites dépendre l'API de service_healthy.
  4. Tuez la base (kill) : observez relance + attente prouvée.
Votre stack redémarre seul et ne route que vers du prouvé sain.

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.

Checklist sortie de section
  • 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.
Auto-évaluation 1-5 : ma stack survivrait-elle à un reboot nocturne sans moi ?mes dépendances attendent-elles le vrai prêt ou un simple ordre ?

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.

Vérifiez votre compréhension

Un service est « Up (unhealthy) ». Que faut-il comprendre ?

Ressources supplémentaires (optionnel, pour aller plus loin)

Examen du niveau 4Questions inédites et durcies pour valider vos acquis