← Blog
Conteneur crème avec une coche verte et une base orange sur un fond lavande clair.
Publié le
2026-10-29

Healthcheck Docker Compose : exemples et diagnostic

Un healthcheck Docker Compose exécute une commande dans un conteneur et indique si le service réussit ce contrôle. Ajoutez depends_on avec condition: service_healthy lorsqu'un autre service doit attendre ce résultat avant de démarrer. Un processus peut être en cours d'exécution alors que l'application se charge encore ou ne répond pas aux requêtes.

Ce guide s'adresse aux développeurs qui exécutent une API ou une petite application multiservice sur un hôte Linux. Il présente un exemple HTTP complet, un modèle de dépendance à une base de données et une méthode de diagnostic. Il précise aussi une limite importante en production : le statut unhealthy ne suffit pas, à lui seul, à déclencher un redémarrage avec Docker Compose.

Définir ce que le contrôle doit vérifier

Décrivez le comportement attendu avant d'écrire la commande. Pour une API, il peut s'agir de « l'application répond à sa route de disponibilité ». Pour un worker, de « l'initialisation est terminée et la file de tâches nécessaire est accessible ». Un indicateur vert n'est utile que si le test correspond au travail attendu du service.

Le contrôle doit rester léger et ne modifier aucune donnée. Évitez d'envoyer des e-mails, de créer des lignes dans une base, de lancer des migrations ou d'appeler une API payante toutes les quelques secondes. Distinguez la disponibilité, qui indique si le service peut accepter du travail, de la vitalité, qui indique s'il répond encore. Une interruption temporaire de la base ne doit pas automatiquement provoquer le redémarrage de toutes les applications qui en dépendent.

Un exemple complet de healthcheck Docker Compose

Créez un nouveau dossier contenant les trois fichiers suivants. Il s'agit d'une démonstration locale, pas d'un serveur web de production. Python est déjà présent dans l'image : le contrôle ne nécessite donc pas l'installation de curl ou de wget.

1. Ajouter un petit service HTTP

Enregistrez ce fichier sous le nom app.py. La route /healthz renvoie une réponse courte et prévisible. Dans une application réelle, reliez cette route aux étapes d'initialisation et aux dépendances indispensables au traitement des requêtes.

from http.server import BaseHTTPRequestHandler, HTTPServer


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        ready = self.path == "/healthz"
        body = b"ok" if ready else b"not found"
        self.send_response(200 if ready else 404)
        self.send_header("Content-Type", "text/plain")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)


if __name__ == "__main__":
    HTTPServer(("0.0.0.0", 8080), Handler).serve_forever()

2. Ajouter la commande de contrôle

Enregistrez ce fichier sous le nom check_health.py. Le test exige le statut HTTP 200 et le contenu attendu. Une redirection vers une page de connexion, une page d'erreur ou une autre réponse positive font échouer le contrôle. La connexion dispose d'un délai de deux secondes ; la commande renvoie le code 0 en cas de réussite et 1 en cas d'échec.

import http.client
import sys

connection = http.client.HTTPConnection("127.0.0.1", 8080, timeout=2)
try:
    connection.request("GET", "/healthz")
    response = connection.getresponse()
    ok = response.status == 200 and response.read(64).strip() == b"ok"
    print("ready" if ok else "readiness check failed")
except (OSError, http.client.HTTPException):
    ok = False
    print("readiness endpoint unavailable")
finally:
    connection.close()
sys.exit(0 if ok else 1)

3. Définir le service dans compose.yaml

services:
  api:
    image: python:3.13-slim
    working_dir: /app
    command: ["python", "app.py"]
    volumes:
      - ./app.py:/app/app.py:ro
      - ./check_health.py:/app/check_health.py:ro
    ports:
      - "127.0.0.1:8080:8080"
    healthcheck:
      test: ["CMD", "python", "/app/check_health.py"]
      interval: 15s
      timeout: 3s
      retries: 3
      start_period: 20s
      start_interval: 2s
    restart: unless-stopped

Le port publié est limité à l'adresse de boucle locale de l'hôte. Dans le conteneur, la sonde contacte le port 8080 de ce même conteneur ; elle n'utilise pas le port publié de l'hôte. Les autres conteneurs du réseau Compose utiliseraient api:8080, conformément aux règles de découverte des services de Docker.

L'exemple utilise une étiquette d'image lisible. Pour une version de production reproductible, choisissez et conservez l'empreinte d'une image testée, intégrez l'application à l'image et utilisez un serveur de production adapté. N'exposez pas directement cette démonstration à Internet.

Régler les intervalles, délais et tentatives

Les valeurs ci-dessus sont des exemples. Ajustez-les en fonction du temps de démarrage mesuré et du coût du contrôle :

  • interval: 15s définit la pause habituelle entre les contrôles.
  • timeout: 3s limite la durée d'une exécution.
  • retries: 3 exige trois échecs consécutifs comptabilisés avant le passage au statut unhealthy.
  • start_period: 20s accorde une période de grâce aux échecs pendant l'initialisation. Un contrôle réussi pendant cette période met fin à cette protection pour les échecs suivants.
  • start_interval: 2s augmente la fréquence des contrôles au démarrage.

start_interval nécessite Docker Compose 2.20.2 ou une version ultérieure, ainsi que Docker Engine 25.0 ou une version ultérieure. Vérifiez les deux composants. La référence Compose décrit la configuration ; la référence des healthchecks Docker explique les états et les délais. Les contrôles continuent après le passage au statut unhealthy : une réussite peut rétablir le statut healthy.

Attendre la disponibilité au démarrage

Depuis le dossier contenant les fichiers, exécutez :

docker compose version
docker version
docker compose config --quiet
docker compose up --wait --wait-timeout 90
docker compose ps

config --quiet vérifie la configuration Compose. up --wait démarre les services en arrière-plan et attend qu'ils soient en cours d'exécution ou, s'ils possèdent un healthcheck, au statut healthy. La limite de 90 secondes concerne l'attente du déploiement, indépendamment du délai de la sonde. Un service sans healthcheck peut satisfaire cette commande simplement en démarrant. Consultez les options de Compose up.

Après le démarrage, appelez http://127.0.0.1:8080/healthz depuis l'hôte. Une fois cette démonstration terminée, docker compose down supprime ses conteneurs et son réseau par défaut. Exécutez cette commande depuis le dossier de l'exemple afin de cibler le bon projet.

Utiliser depends_on et service_healthy pour une base

Le démarrage du processus d'une base ne prouve pas qu'elle accepte les connexions. Si une application a besoin de PostgreSQL pendant son initialisation, ajoutez un contrôle au service de base de données et faites dépendre l'application de son état healthy.

Le fragment suivant doit être intégré à un fichier Compose qui définit déjà les services api et PostgreSQL db. Ce n'est pas un second exemple autonome. Le service de base doit déjà disposer de son image, de ses identifiants, de son stockage et des variables d'environnement POSTGRES_USER et POSTGRES_DB.

services:
  api:
    depends_on:
      db:
        condition: service_healthy
  db:
    healthcheck:
      test:
        - CMD-SHELL
        - 'pg_isready -h 127.0.0.1 -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"'
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

CMD exécute directement le programme indiqué. CMD-SHELL passe par l'interpréteur de commandes du conteneur, nécessaire ici pour développer les variables. L'échappement par deux signes dollar empêche Compose de remplacer la variable sur l'hôte : son développement se fait dans le conteneur.

pg_isready vérifie l'état des connexions du serveur. Il ne vérifie ni la fin des migrations ni la capacité de l'application à exécuter les requêtes nécessaires. Si les migrations doivent précéder le démarrage, représentez-les séparément ; Compose propose la condition service_completed_successfully pour une tâche qui doit se terminer avec succès.

Les conditions de dépendance déterminent l'ordre de démarrage. Elles n'arrêtent pas continuellement l'API si la base devient ensuite unhealthy. L'application doit toujours prévoir des tentatives de reconnexion et un comportement adapté lorsqu'une dépendance est indisponible.

Examiner un conteneur unhealthy avant de modifier les délais

Récupérez d'abord l'identifiant du conteneur, puis remplacez CONTAINER_ID dans la deuxième commande :

docker compose ps -q api
docker inspect --format "{{json .State.Health}}" CONTAINER_ID
docker compose exec api python /app/check_health.py
docker compose logs --tail 100 api

Le journal du healthcheck indique ce que la sonde a signalé. Le journal de l'application aide à comprendre ce que le service faisait. Avant d'allonger les délais, recherchez ces causes :

  • Exécutable absent : une image minimale peut ne pas contenir curl. Utilisez un outil présent ou ajoutez-le lors de la construction de l'image.
  • Adresse incorrecte : dans un conteneur ordinaire, localhost désigne ce conteneur. Pour joindre un autre service, utilisez son nom et son port interne.
  • Critère de réussite inadapté : une page d'accueil ou une redirection d'authentification peut masquer une API défaillante. Vérifiez la bonne route et sa réponse.
  • Initialisation lente : examinez les opérations de démarrage avant d'allonger la période de grâce.
  • Ressources saturées : une instance surchargée peut ralentir l'application et sa sonde. Mesurez la mémoire, le CPU et la latence des requêtes.

Le statut unhealthy redémarre-t-il le conteneur ?

Non. Avec Docker Engine et Compose classiques, restart: unless-stopped réagit à l'arrêt du conteneur. Il ne redémarre pas un conteneur encore actif au seul motif que son état de santé a changé. La documentation des politiques de redémarrage précise ce comportement.

Distinguez aussi ce réglage du service de restart: true placé sous depends_on. Ce dernier peut redémarrer un service dépendant après une opération Compose explicite sur sa dépendance. Il ne constitue pas une récupération continue fondée sur l'état de santé.

Décidez de la réponse à apporter à un échec : alerter un opérateur, retirer une instance du trafic à l'aide d'un système configuré séparément, ou utiliser un orchestrateur avec une politique de récupération adaptée. Un redémarrage ne corrige pas des identifiants manquants, une migration échouée ou une panne de base de données.

Exécuter l'exemple sur une VM

Pour préparer l'hôte, consultez notre guide pour exécuter Docker sur une VM Compute with Hivenet. Une fois Docker disponible, les contrôles de disponibilité restent une responsabilité de configuration et d'exploitation de votre application.

Une sonde locale réussie ne valide ni le DNS public, ni TLS, ni le proxy inverse, ni le pare-feu. Testez séparément le chemin emprunté par les utilisateurs. Notre guide pour exposer un service depuis une VM aborde ces choix de connectivité.

Questions sur les healthchecks Docker Compose

Peut-on remplacer le healthcheck d'un Dockerfile ?

Oui. Le healthcheck du service Compose peut remplacer les paramètres de l'image. Pour désactiver volontairement un contrôle hérité, utilisez healthcheck: {disable: true}. Vérifiez d'abord quelles dépendances ou fonctions de surveillance s'appuient sur ce contrôle.

Peut-on définir plusieurs healthchecks par conteneur ?

Docker expose un seul résultat par conteneur. Si plusieurs conditions sont nécessaires, réunissez-les dans un script à durée limitée qui échoue dès qu'une condition requise n'est pas satisfaite. Gardez une sortie courte et utile au diagnostic.

Le statut healthy prouve-t-il que l'application fonctionne ?

Il confirme uniquement le comportement testé. Conservez les tests applicatifs, la surveillance externe et les procédures de récupération. Une sonde limitée à une route ne garantit pas la disponibilité de tous les parcours utilisateurs.

Votre prochaine charge de travail sur Hivenet.

Choisissez une charge de travail d’IA, de calcul ou de stockage à tester sur Hivenet, ou échangez avec notre équipe sur sa mise en production.