[{"data":1,"prerenderedAt":172},["ShallowReactive",2],{"seo-verification":3,"blog-docker-compose-depends-on-healthcheck-fr":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":12,"excerpt":13,"readTime":14,"views":15,"isPinned":16,"publishedAt":17,"category":18,"categories":23,"featuredImage":25,"bgImage":26,"posterImage":27,"relatedSolution":25,"intro":28,"sections":29,"ctaTitle":117,"ctaBody":118,"ctaButton":119,"ctaUrl":120,"relatedPosts":121},282,"docker-compose-depends-on-healthcheck",{"fr":8,"en":10,"ar":11},"depends-on-is-not-enough-postgresql-healthcheck-in-compose","depends-on-لا-يكفي-healthcheck-لـ-postgresql-في-compose","depends_on ne suffit pas : healthcheck PostgreSQL dans Compose","Pourquoi `depends_on` seul ne garantit pas que PostgreSQL est prêt, et comment configurer un healthcheck fiable avec `service_healthy` pour éviter les races conditions.",9,0,false,"2026-08-19T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},3,"Déploiement","deploiement","bg-success\u002F10 text-success",[24],{"id":19,"name":20,"slug":21,"color":22,"icon":21},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdocker-compose-depends-on-healthcheck-poster.svg","Votre stack Docker démarre, la base de données passe à l'état `running` — et votre application plante immédiatement avec `connection refused` ou `FATAL: role does not exist`. La cause est presque toujours la même : `depends_on` par défaut attend que le conteneur démarre, pas que le service soit opérationnel. Ce guide vous montre comment configurer un healthcheck PostgreSQL fiable dans `docker-compose.yml` pour éliminer cette race condition une fois pour toutes.",[30,34,44,47,75,107,111,114],{"type":31,"title":32,"body":33},"h2","Pourquoi `depends_on` par défaut échoue","Par défaut, `depends_on` utilise la condition `service_started`. Cela signifie que Docker attend uniquement que le conteneur cible soit **lancé** — autrement dit, que son processus principal soit démarré. Cela ne dit rien sur l'état interne du service.\n\nPostgreSQL, comme la plupart des bases de données, traverse plusieurs phases à l'initialisation : l'image officielle exécute des scripts d'amorçage, crée les rôles, initialise les extensions et positionne le cluster avant de commencer à accepter des connexions. Cette séquence peut prendre de quelques secondes à plus de trente secondes sur un VPS avec un disque chaud, un volume non préparé ou un gros jeu d'extensions.\n\nPendant ce temps, votre application — qui respecte pourtant la directive `depends_on` — tente déjà de se connecter, et reçoit un refus net.",{"type":35,"title":36,"items":37},"ul","Les conséquences pratiques d'une race condition au démarrage",[38,39,40,41,42,43],"**`connection refused`** — le socket TCP de PostgreSQL n'est pas encore ouvert, l'application échoue au premier appel PDO ou SQLAlchemy.","**`FATAL: role does not exist`** — PostgreSQL écoute, mais les scripts d'initialisation (`docker-entrypoint-initdb.d`) n'ont pas encore créé le rôle ni la base de données.","**`FATAL: the database system is starting up`** — le cluster est en cours de récupération après un arrêt propre ; les connexions sont temporairement refusées.","**Crash loop silencieux** — Docker `restart: unless-stopped` relance l'application indéfiniment, les logs se répètent, et le problème passe pour une erreur applicative.","**Faux positifs en CI** — les tests d'intégration échouent de manière intermittente selon la vitesse de démarrage du runner.","**Dépendances en cascade** — une API qui dépend d'une appli qui dépend de la base hérite du même problème si la chaîne `depends_on` n'est pas uniformément correcte.",{"type":31,"title":45,"body":46},"Prérequis : Docker Compose v2 et le plugin officiel","La condition `service_healthy` n'est **pas** disponible dans Docker Compose v1 (le binaire `docker-compose` en Python, désormais obsolète). Elle est supportée depuis **Docker Compose v2**, distribué comme plugin Go sous la commande `docker compose` (sans tiret).\n\nPour vérifier votre version :\n\n```bash\ndocker compose version\n```\n\nLa sortie doit afficher `Docker Compose version v2.x.x` ou supérieur. Sur Debian 12 et Ubuntu 22.04+, le plugin est disponible dans les dépôts officiels Docker. Si vous avez encore `docker-compose` (v1), migrez : le projet est archivé et ne reçoit plus de correctifs de sécurité.\n\nAucune dépendance supplémentaire n'est requise pour PostgreSQL : `pg_isready` est un outil natif de l'image officielle `postgres`, présent dans tous les tags depuis des années.",{"type":48,"title":49,"steps":50},"steps","Configurer un healthcheck PostgreSQL fiable, étape par étape",[51,54,57,60,63,66,69,72],{"title":52,"body":53},"Comprendre service_started vs service_healthy","`depends_on` accepte trois conditions :\n\n- `service_started` (défaut) — attend que le conteneur soit simplement démarré.\n- `service_healthy` — attend que le healthcheck du conteneur renvoie `healthy`.\n- `service_completed_successfully` — pour les conteneurs à courte durée de vie (jobs, migrations).\n\nPour toute base de données, `service_healthy` est la seule condition qui garantit que le service accepte des connexions.",{"title":55,"body":56},"Écrire le healthcheck PostgreSQL dans le service `db`","Ajoutez le bloc `healthcheck` directement dans la définition du service `db` :\n\n```yaml\nservices:\n  db:\n    image: postgres:16\n    environment:\n      POSTGRES_USER: app\n      POSTGRES_PASSWORD: secret\n      POSTGRES_DB: appdb\n    healthcheck:\n      test: [\"CMD\", \"pg_isready\", \"-U\", \"app\", \"-d\", \"appdb\"]\n      interval: 5s\n      timeout: 5s\n      retries: 5\n      start_period: 30s\n```\n\nLe champ `test` reçoit une liste : le premier élément est `CMD` (Docker exécute la commande directement), suivi des arguments. `pg_isready` renvoie `0` si PostgreSQL est prêt à accepter des connexions sur l'utilisateur et la base indiqués, et un code non nul sinon — ce que Docker interprète comme `healthy` ou `unhealthy`.",{"title":58,"body":59},"Comprendre le rôle de `start_period`","`start_period` est la **fenêtre de grâce** accordée au conteneur pour s'initialiser avant que les échecs de healthcheck ne commencent à être comptabilisés dans `retries`. Pendant cette fenêtre, Docker lance bien le healthcheck, mais un échec n'incrémente pas le compteur.\n\nSans `start_period`, un PostgreSQL qui met 15 secondes à s'initialiser échouerait ses 5 premiers checks (`interval: 5s` × 5 tentatives = 25 secondes) et passerait en `unhealthy` avant même d'être opérationnel.\n\nLa valeur recommandée est **30 secondes** pour un PostgreSQL standard : suffisamment longue pour absorber les initialisations lentes (premier démarrage avec volume vide, extensions lourdes) sans retarder inutilement le démarrage en régime permanent. `interval` et `start_period` sont distincts : `interval` cadence les vérifications en régime normal, `start_period` protège la phase d'amorçage.",{"title":61,"body":62},"Écrire le `depends_on` avec `condition: service_healthy`","Dans chaque service qui dépend de la base, remplacez la forme courte de `depends_on` par la forme longue avec condition :\n\n```yaml\nservices:\n  app:\n    image: monapp:latest\n    depends_on:\n      db:\n        condition: service_healthy\n    environment:\n      DATABASE_URL: postgresql:\u002F\u002Fapp:secret@db:5432\u002Fappdb\n```\n\nAvec cette configuration, Docker attend que le healthcheck du service `db` renvoie `healthy` avant de démarrer `app`. Si `db` passe en `unhealthy` après `retries` échecs, `app` ne démarre pas.",{"title":64,"body":65},"Tester avec `docker compose up`","Lancez la stack et observez le séquencement :\n\n```bash\ndocker compose up\n```\n\nVous verrez dans les logs des lignes du type :\n\n```\ndb  | database system is ready to accept connections\napp | Waiting for db to be healthy...\napp | Starting application server\n```\n\nPour vérifier l'état du healthcheck à tout moment :\n\n```bash\ndocker inspect \u003Cnom_du_conteneur_db> | grep -A 5 '\"Health\"'\n```\n\nLa sortie indique `Status: healthy`, `starting` ou `unhealthy`, et liste les dernières sorties du check.",{"title":67,"body":68},"Cas Redis : healthcheck adapté","Redis ne dispose pas de `redis-isready`, mais son équivalent est `redis-cli ping` :\n\n```yaml\n  redis:\n    image: redis:7-alpine\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"ping\"]\n      interval: 5s\n      timeout: 3s\n      retries: 5\n      start_period: 10s\n```\n\n`redis-cli ping` renvoie `PONG` et le code de sortie `0` si Redis accepte les connexions. Comme Redis démarre plus vite que PostgreSQL, `start_period: 10s` est généralement suffisant.",{"title":70,"body":71},"Cas MySQL \u002F MariaDB : `mysqladmin ping`","Pour MySQL ou MariaDB, utilisez `mysqladmin ping` :\n\n```yaml\n  mysql:\n    image: mariadb:11\n    environment:\n      MYSQL_ROOT_PASSWORD: secret\n      MYSQL_DATABASE: appdb\n    healthcheck:\n      test: [\"CMD\", \"mysqladmin\", \"ping\", \"-h\", \"localhost\", \"-u\", \"root\", \"-psecret\"]\n      interval: 5s\n      timeout: 5s\n      retries: 5\n      start_period: 30s\n```\n\nAttention : le mot de passe est concaténé directement à `-p` sans espace (`-psecret`), c'est le comportement attendu de `mysqladmin`. Cette commande s'affiche dans `docker inspect`, donc préférez un secret Compose ou une variable d'environnement si la confidentialité est une contrainte.",{"title":73,"body":74},"Dépannage : quatre erreurs fréquentes","**`pg_isready: command not found`** — vous n'utilisez pas l'image officielle `postgres` (ou une image dérivée qui l'inclut). Vérifiez avec `docker compose exec db which pg_isready`.\n\n**Healthcheck en boucle, jamais `healthy`** — le `test` ne renvoie jamais `0`. Testez manuellement : `docker compose exec db pg_isready -U app -d appdb`. Si la commande échoue, vérifiez les variables d'environnement `POSTGRES_USER` et `POSTGRES_DB`.\n\n**`start_period` trop court** — sur un premier démarrage avec un volume vide, PostgreSQL peut prendre plus de 30 secondes. Augmentez à `60s` ou observez les logs : `database system was shut down at … LOG:  database system is ready to accept connections` indique le délai réel.\n\n**Conteneur en `unhealthy` permanent** — après `retries` échecs, Docker marque le conteneur `unhealthy` mais ne le redémarre pas (c'est le rôle de `restart`). Consultez `docker inspect` pour voir la sortie des derniers checks et identifier la commande qui échoue.",{"type":76,"title":77,"headers":78,"rows":82},"comparison","Comportement par défaut vs avec healthcheck",[79,80,81],"Cas","Comportement par défaut (`service_started`)","Avec `service_healthy`",[83,87,91,95,99,103],[84,85,86],"Premier démarrage, volume vide","App démarre avant que la base soit prête → crash loop","App attend que PostgreSQL soit initialisé et accepte les connexions",[88,89,90],"Redémarrage après un arrêt propre","App peut démarrer pendant la phase de recovery PostgreSQL","App reste en attente jusqu'à la fin de la recovery",[92,93,94],"Base lente (extensions, gros init)","Race condition selon la vitesse du host","Pas de race condition : le healthcheck valide l'état réel",[96,97,98],"Dépendances en cascade (app → worker → db)","Chaque maillon doit gérer lui-même les tentatives de reconnexion","La chaîne de conditions garantit l'ordre de démarrage",[100,101,102],"Tests d'intégration en CI","Résultats intermittents selon la vitesse du runner","Résultats déterministes",[104,105,106],"Redis ou MySQL à la place de PostgreSQL","Même problème, `depends_on` par défaut ne fait pas de distinction","Même solution, commande de check adaptée à chaque moteur",{"type":108,"title":109,"body":110},"tip","`pg_isready` ou `SELECT 1` : lequel choisir ?","On voit souvent deux variantes de healthcheck PostgreSQL dans la nature :\n\n- `[\"CMD\", \"pg_isready\", \"-U\", \"postgres\"]`\n- `[\"CMD-SHELL\", \"psql -U postgres -c 'SELECT 1'\"]\"`\n\n`pg_isready` est **plus fiable** pour une raison simple : il teste uniquement la capacité du serveur à accepter des connexions TCP, sans ouvrir de session SQL. Il renvoie `0` dès que le serveur écoute et accepte la poignée de main, ce qui est exactement ce dont une application a besoin pour tenter sa propre connexion.\n\n`SELECT 1` via `psql` ouvre une vraie session SQL et exécute une requête. C'est un test plus profond, mais il peut échouer pour des raisons non liées à la disponibilité du serveur (quota de connexions atteint, `pg_hba.conf` mal configuré). Pour un healthcheck, le test minimal et direct est préférable.",{"type":108,"title":112,"body":113},"Adapter le healthcheck à Redis et MySQL","Pour Redis, remplacez `pg_isready` par `CMD redis-cli PING` — la commande renvoie `PONG` dès que le serveur accepte des connexions. Pour MySQL ou MariaDB, utilisez `CMD mysqladmin ping -h localhost -u root --password=$$MYSQL_ROOT_PASSWORD` : ajustez `start_period: 60s` car l'initialisation d'une base MySQL prend plus de temps que PostgreSQL. Le pattern `condition: service_healthy` est identique quel que soit le service cible.",{"type":31,"title":115,"body":116},"Maillage et prochaines étapes","Le healthcheck `service_healthy` est l'un des réglages de robustesse à activer en production. Plusieurs autres points méritent la même attention avant un déploiement durable : politique de redémarrage `restart: unless-stopped`, limites de ressources `deploy.resources.limits`, et rotation des logs `logging.options`. Retrouvez la checklist complète dans **Docker Compose en production : 10 points à vérifier**.\n\nSi votre stack grandit — plusieurs services, plusieurs hôtes — un reverse proxy comme Caddy ou Traefik s'impose pour gérer le routage HTTPS. Le guide **Caddy, Traefik ou Nginx Proxy Manager** détaille les critères de choix selon votre profil.\n\nPour automatiser le déploiement de l'ensemble de l'infrastructure (VPS, Docker, configuration) de façon reproductible, **Ansible pour automatiser vos serveurs VPS** vous guidera pas à pas.","Hébergez votre stack Docker sur un VPS dédié","Un VPS ServOrbit vous donne l'accès root, une IPv4 dédiée et les ressources nécessaires pour faire tourner vos stacks Docker Compose en production. Déployez en quelques minutes.","Déployer ma stack sur VPS","\u002Fvps-cloud",[122,136,153],{"id":123,"slug":124,"slugs":125,"title":128,"excerpt":129,"readTime":130,"views":15,"isPinned":16,"publishedAt":131,"category":132,"categories":133,"featuredImage":25,"bgImage":26,"posterImage":135,"relatedSolution":25},229,"docker-compose-production-checklist",{"fr":124,"en":126,"ar":127},"docker-compose-in-production-10-point-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","Docker Compose en production : checklist des 10 points","Checklist Docker Compose en production : 10 paramètres essentiels, gestion des secrets sans downtime, sauvegarde volumes sans corruption, CVE-2026-17106.",14,"2026-08-06T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[134],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":137,"slug":138,"slugs":139,"title":142,"excerpt":143,"readTime":144,"views":15,"isPinned":16,"publishedAt":131,"category":145,"categories":150,"featuredImage":25,"bgImage":26,"posterImage":152,"relatedSolution":25},227,"choisir-reverse-proxy-vps-caddy-traefik-nginx",{"fr":138,"en":140,"ar":141},"caddy-traefik-or-nginx-proxy-manager-which-to-choose","caddy-أم-traefik-أم-nginx-proxy-manager-أيهما-تختار","Caddy, Traefik ou Nginx Proxy Manager : lequel choisir ?","Guide de choix entre Caddy, Traefik et Nginx Proxy Manager pour self-hosters Docker sur VPS. Critères, tableau comparatif et recommandations par profil.",10,{"id":146,"name":147,"slug":148,"color":149,"icon":148},5,"Comparatif","comparatif","bg-info\u002F10 text-info",[151],{"id":146,"name":147,"slug":148,"color":149,"icon":148},"\u002Fblog\u002Fcovers\u002Fchoisir-reverse-proxy-vps-caddy-traefik-nginx-poster.svg",{"id":154,"slug":155,"slugs":156,"title":159,"excerpt":160,"readTime":161,"views":162,"isPinned":16,"publishedAt":163,"category":164,"categories":169,"featuredImage":25,"bgImage":26,"posterImage":171,"relatedSolution":25},236,"ansible-automatiser-serveurs-vps",{"fr":155,"en":157,"ar":158},"automating-vps-server-management-with-ansible","أتمتة-إدارة-خوادم-vps-باستخدام-ansible","Automatiser la gestion de ses serveurs VPS avec Ansible","Automatisez la gestion d'une flotte de serveurs VPS avec Ansible : inventaire, playbooks, rôles et Vault pour une infrastructure reproductible.",11,1,"2026-08-08T00:00:00+00:00",{"id":165,"name":166,"slug":167,"color":168,"icon":167},2,"Automatisation","automatisation","bg-brand-action\u002F10 text-brand-action",[170],{"id":165,"name":166,"slug":167,"color":168,"icon":167},"\u002Fblog\u002Fcovers\u002Fansible-automatiser-serveurs-vps-poster.svg",1787580971469]