
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é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.
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.
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()
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)
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.
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.
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.
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.
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 :
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.
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é.
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.
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.
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.
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.