[{"data":1,"prerenderedAt":685},["ShallowReactive",2],{"navigation":3,"/docs/deployment-and-production/health-checks":249,"/docs/deployment-and-production/health-checks-surround":680},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","/docs","docs",[9,12,48,77,132,160,185,206,219,236],{"title":10,"path":6,"stem":11},"","docs/index",{"title":13,"path":14,"stem":15,"children":16,"icon":47},"Getting Started","/docs/getting-started","docs/1.getting-started/1.index",[17,19,23,27,31,35,39,43],{"title":18,"path":14,"stem":15},"Introduction",{"title":20,"path":21,"stem":22},"Container basics","/docs/getting-started/container-basics","docs/1.getting-started/2.container-basics",{"title":24,"path":25,"stem":26},"Installation","/docs/getting-started/installation","docs/1.getting-started/3.installation",{"title":28,"path":29,"stem":30},"These images vs others","/docs/getting-started/these-images-vs-others","docs/1.getting-started/4.these-images-vs-others",{"title":32,"path":33,"stem":34},"Choosing an image","/docs/getting-started/choosing-an-image","docs/1.getting-started/5.choosing-an-image",{"title":36,"path":37,"stem":38},"Default configurations","/docs/getting-started/default-configurations","docs/1.getting-started/6.default-configurations",{"title":40,"path":41,"stem":42},"Migrating from official PHP images","/docs/getting-started/migrating-from-official-php-images","docs/1.getting-started/7.migrating-from-official-php-images",{"title":44,"path":45,"stem":46},"Contributing","/docs/getting-started/contributing","docs/1.getting-started/99.contributing",false,{"title":49,"path":50,"stem":51,"children":52,"page":47},"Image Variations","/docs/image-variations","docs/2.image-variations",[53,57,61,65,69,73],{"title":54,"path":55,"stem":56},"CLI","/docs/image-variations/cli","docs/2.image-variations/cli",{"title":58,"path":59,"stem":60},"FPM","/docs/image-variations/fpm","docs/2.image-variations/fpm",{"title":62,"path":63,"stem":64},"FPM-Apache","/docs/image-variations/fpm-apache","docs/2.image-variations/fpm-apache",{"title":66,"path":67,"stem":68},"FPM-NGINX","/docs/image-variations/fpm-nginx","docs/2.image-variations/fpm-nginx",{"title":70,"path":71,"stem":72},"FrankenPHP","/docs/image-variations/frankenphp","docs/2.image-variations/frankenphp",{"title":74,"path":75,"stem":76},"NGINX Unit (removed)","/docs/image-variations/unit","docs/2.image-variations/unit",{"title":78,"path":79,"stem":80,"children":81,"page":47},"Framework Guides","/docs/framework-guides","docs/3.framework-guides",[82,123],{"title":83,"icon":47,"defaultOpen":47,"path":84,"stem":85,"children":86,"page":47},"Laravel","/docs/framework-guides/laravel","docs/3.framework-guides/1.laravel",[87,91,95,99,103,107,111,115,119],{"title":88,"path":89,"stem":90},"Automations","/docs/framework-guides/laravel/automations","docs/3.framework-guides/1.laravel/1.automations",{"title":92,"path":93,"stem":94},"Running workers","/docs/framework-guides/laravel/workers","docs/3.framework-guides/1.laravel/2.workers",{"title":96,"path":97,"stem":98},"Health checks","/docs/framework-guides/laravel/health-checks","docs/3.framework-guides/1.laravel/3.health-checks",{"title":100,"path":101,"stem":102},"Horizon","/docs/framework-guides/laravel/horizon","docs/3.framework-guides/1.laravel/4.horizon",{"title":104,"path":105,"stem":106},"Nightwatch","/docs/framework-guides/laravel/nightwatch","docs/3.framework-guides/1.laravel/5.nightwatch",{"title":108,"path":109,"stem":110},"Octane","/docs/framework-guides/laravel/octane","docs/3.framework-guides/1.laravel/6.octane",{"title":112,"path":113,"stem":114},"Queue","/docs/framework-guides/laravel/queue","docs/3.framework-guides/1.laravel/7.queue",{"title":116,"path":117,"stem":118},"Reverb","/docs/framework-guides/laravel/reverb","docs/3.framework-guides/1.laravel/8.reverb",{"title":120,"path":121,"stem":122},"Task scheduler","/docs/framework-guides/laravel/task-scheduler","docs/3.framework-guides/1.laravel/9.task-scheduler",{"title":124,"icon":47,"defaultOpen":47,"path":125,"stem":126,"children":127,"page":47},"WordPress","/docs/framework-guides/wordpress","docs/3.framework-guides/2.wordpress",[128],{"title":129,"path":130,"stem":131},"Using WordPress with Docker","/docs/framework-guides/wordpress/using-wordpress-with-docker","docs/3.framework-guides/2.wordpress/4.using-wordpress-with-docker",{"title":133,"path":134,"stem":135,"children":136,"page":47},"Deployment And Production","/docs/deployment-and-production","docs/4.deployment-and-production",[137,141,145,148,152,156],{"title":138,"path":139,"stem":140},"Packaging your app for deployment","/docs/deployment-and-production/packaging-your-app-for-deployment","docs/4.deployment-and-production/1.packaging-your-app-for-deployment",{"title":142,"path":143,"stem":144},"Configuring SSL","/docs/deployment-and-production/configuring-ssl","docs/4.deployment-and-production/2.configuring-ssl",{"title":96,"path":146,"stem":147},"/docs/deployment-and-production/health-checks","docs/4.deployment-and-production/3.health-checks",{"title":149,"path":150,"stem":151},"Configuring trusted proxies","/docs/deployment-and-production/configuring-trusted-proxies","docs/4.deployment-and-production/4.configuring-trusted-proxies",{"title":153,"path":154,"stem":155},"Production performance tuning","/docs/deployment-and-production/production-performance-tuning","docs/4.deployment-and-production/5.production-performance-tuning",{"title":157,"path":158,"stem":159},"Choosing a host","/docs/deployment-and-production/choosing-a-host","docs/4.deployment-and-production/6.choosing-a-host",{"title":161,"icon":47,"defaultOpen":47,"path":162,"stem":163,"children":164,"page":47},"Customization","/docs/customizing-the-image","docs/5.customizing-the-image",[165,169,173,177,181],{"title":166,"path":167,"stem":168},"Changing php.ini settings","/docs/customizing-the-image/changing-common-php-settings","docs/5.customizing-the-image/1.changing-common-php-settings",{"title":170,"path":171,"stem":172},"Installing PHP extensions","/docs/customizing-the-image/installing-additional-php-extensions","docs/5.customizing-the-image/2.installing-additional-php-extensions",{"title":174,"path":175,"stem":176},"Adding start up scripts","/docs/customizing-the-image/adding-your-own-start-up-scripts","docs/5.customizing-the-image/3.adding-your-own-start-up-scripts",{"title":178,"path":179,"stem":180},"Using S6 Overlay","/docs/customizing-the-image/using-s6-overlay","docs/5.customizing-the-image/4.using-s6-overlay",{"title":182,"path":183,"stem":184},"Understanding file permissions","/docs/customizing-the-image/understanding-file-permissions","docs/5.customizing-the-image/5.understanding-file-permissions",{"title":186,"icon":47,"defaultOpen":47,"path":187,"stem":188,"children":189,"page":47},"Upgrading","/docs/upgrading","docs/6.upgrading",[190,194,198,202],{"title":191,"path":192,"stem":193},"Upgrade guide","/docs/upgrading/upgrade-guide","docs/6.upgrading/1.upgrade-guide",{"title":195,"path":196,"stem":197},"Upgrade to v5","/docs/upgrading/upgrade-to-v5","docs/6.upgrading/2.upgrade-to-v5",{"title":199,"path":200,"stem":201},"Upgrade to v4","/docs/upgrading/upgrade-to-v4","docs/6.upgrading/3.upgrade-to-v4",{"title":203,"path":204,"stem":205},"Upgrade to v3","/docs/upgrading/upgrade-to-v3","docs/6.upgrading/4.upgrade-to-v3",{"title":207,"path":208,"stem":209,"children":210,"page":47},"Troubleshooting","/docs/troubleshooting","docs/7.troubleshooting",[211,215],{"title":212,"path":213,"stem":214},"Common issues","/docs/troubleshooting/common-issues","docs/7.troubleshooting/1.common-issues",{"title":216,"path":217,"stem":218},"Getting help","/docs/troubleshooting/getting-help","docs/7.troubleshooting/2.getting-help",{"title":220,"path":221,"stem":222,"children":223,"page":47},"Security","/docs/security","docs/8.security",[224,228,232],{"title":225,"path":226,"stem":227},"How images are built","/docs/security/how-images-are-built","docs/8.security/1.how-images-are-built",{"title":229,"path":230,"stem":231},"Verifying images","/docs/security/verifying-images","docs/8.security/2.verifying-images",{"title":233,"path":234,"stem":235},"Vulnerability scanning","/docs/security/vulnerability-scanning","docs/8.security/3.vulnerability-scanning",{"title":237,"path":238,"stem":239,"children":240,"page":47},"Reference","/docs/reference","docs/9.reference",[241,245],{"title":242,"path":243,"stem":244},"Environment variable specification","/docs/reference/environment-variable-specification","docs/9.reference/1.environment-variable-specification",{"title":246,"path":247,"stem":248},"Command reference","/docs/reference/command-reference","docs/9.reference/2.command-reference",{"id":250,"title":96,"body":251,"description":671,"extension":672,"links":673,"meta":674,"navigation":677,"path":146,"redirect":673,"seo":678,"stem":147,"__hash__":679},"docs/docs/4.deployment-and-production/3.health-checks.md",{"type":252,"value":253,"toc":664},"minimark",[254,274,279,388,415,428,432,446,508,511,522,531,535,538,611,618,622,632,635,641,645,660],[255,256,257],"lead-p",{},[258,259,260,261,265,266,269,270,273],"p",{},"Every image except ",[262,263,264],"code",{},"cli"," ships a Docker ",[262,267,268],{},"HEALTHCHECK",". It works with no configuration. Set ",[262,271,272],{},"HEALTHCHECK_PATH"," to check a route in your app instead of the web server alone.",[275,276,278],"h2",{"id":277},"what-each-variation-checks","What each variation checks",[280,281,282,298],"table",{},[283,284,285],"thead",{},[286,287,288,292,295],"tr",{},[289,290,291],"th",{},"Variation",[289,293,294],{},"Check",[289,296,297],{},"Passes when",[299,300,301,321,338,355,377],"tbody",{},[286,302,303,309,318],{},[304,305,306],"td",{},[262,307,308],{},"fpm-nginx",[304,310,311,314,315],{},[262,312,313],{},"curl"," to ",[262,316,317],{},"http://localhost:${NGINX_HTTP_PORT}${HEALTHCHECK_PATH}",[304,319,320],{},"NGINX and PHP-FPM both answer",[286,322,323,328,335],{},[304,324,325],{},[262,326,327],{},"fpm-apache",[304,329,330,314,332],{},[262,331,313],{},[262,333,334],{},"http://localhost:${APACHE_HTTP_PORT}${HEALTHCHECK_PATH}",[304,336,337],{},"Apache and PHP-FPM both answer",[286,339,340,345,352],{},[304,341,342],{},[262,343,344],{},"frankenphp",[304,346,347,314,349],{},[262,348,313],{},[262,350,351],{},"http://localhost:${CADDY_HTTP_PORT}${HEALTHCHECK_PATH}",[304,353,354],{},"Caddy answers",[286,356,357,362,374],{},[304,358,359],{},[262,360,361],{},"fpm",[304,363,364],{},[365,366,371],"a",{"href":367,"rel":368,"target":370},"https://github.com/renatomefi/php-fpm-healthcheck",[369],"nofollow","_blank",[262,372,373],{},"php-fpm-healthcheck",[304,375,376],{},"PHP-FPM's status page answers",[286,378,379,383,386],{},[304,380,381],{},[262,382,264],{},[304,384,385],{},"None",[304,387],{},[258,389,390,392,393,396,397,399,400,402,403,405,406,396,409,411,412,414],{},[262,391,272],{}," defaults to ",[262,394,395],{},"/healthcheck",". In ",[262,398,308],{}," and ",[262,401,327],{},", the web server passes ",[262,404,395],{}," to PHP-FPM's ping page, which returns ",[262,407,408],{},"OK",[262,410,344],{},", Caddy returns ",[262,413,408],{}," itself. Neither one reaches your app.",[258,416,417,418,420,421,424,425,427],{},"The check follows the port variable when you change it. ",[262,419,313],{}," follows redirects and skips certificate checks, so the check still passes with ",[262,422,423],{},"SSL_MODE=full",", where the HTTP port redirects to HTTPS. Requests to ",[262,426,272],{}," stay out of the access log.",[275,429,431],{"id":430},"check-your-app-instead","Check your app instead",[258,433,434,435,437,438,441,442,445],{},"Set ",[262,436,272],{}," to a route in your app that returns ",[262,439,440],{},"200",", such as Laravel's ",[262,443,444],{},"/up",":",[447,448,453],"pre",{"className":449,"code":450,"filename":451,"language":452,"meta":10,"style":10},"language-yaml shiki shiki-themes github-dark","services:\n  app:\n    image: my-org/my-app:1.0.0\n    environment:\n      HEALTHCHECK_PATH: \"/up\"\n","compose.yml","yaml",[262,454,455,468,476,489,497],{"__ignoreMap":10},[456,457,460,464],"span",{"class":458,"line":459},"line",1,[456,461,463],{"class":462},"s4JwU","services",[456,465,467],{"class":466},"s95oV",":\n",[456,469,471,474],{"class":458,"line":470},2,[456,472,473],{"class":462},"  app",[456,475,467],{"class":466},[456,477,479,482,485],{"class":458,"line":478},3,[456,480,481],{"class":462},"    image",[456,483,484],{"class":466},": ",[456,486,488],{"class":487},"sU2Wk","my-org/my-app:1.0.0\n",[456,490,492,495],{"class":458,"line":491},4,[456,493,494],{"class":462},"    environment",[456,496,467],{"class":466},[456,498,500,503,505],{"class":458,"line":499},5,[456,501,502],{"class":462},"      HEALTHCHECK_PATH",[456,504,484],{"class":466},[456,506,507],{"class":487},"\"/up\"\n",[258,509,510],{},"The check now fails when your app can't boot, not only when the web server is down. Pick a route that answers quickly.",[258,512,513,514,399,516,518,519,521],{},"In ",[262,515,308],{},[262,517,327],{},", S6 Overlay requests the same path at startup. It marks the web server ready once the path returns ",[262,520,440],{},".",[258,523,524,527,528,530],{},[365,525,526],{"href":97},"Laravel health checks"," covers ",[262,529,444],{}," and the checks for queue, Horizon, and scheduler containers.",[275,532,534],{"id":533},"timing","Timing",[258,536,537],{},"All four checks use the same settings:",[280,539,540,550],{},[283,541,542],{},[286,543,544,547],{},[289,545,546],{},"Setting",[289,548,549],{},"Value",[299,551,552,564,576,588,599],{},[286,553,554,559],{},[304,555,556],{},[262,557,558],{},"start_period",[304,560,561],{},[262,562,563],{},"60s",[286,565,566,571],{},[304,567,568],{},[262,569,570],{},"start_interval",[304,572,573],{},[262,574,575],{},"3s",[286,577,578,583],{},[304,579,580],{},[262,581,582],{},"interval",[304,584,585],{},[262,586,587],{},"10s",[286,589,590,595],{},[304,591,592],{},[262,593,594],{},"timeout",[304,596,597],{},[262,598,575],{},[286,600,601,606],{},[304,602,603],{},[262,604,605],{},"retries",[304,607,608],{},[262,609,610],{},"3",[258,612,613,614,617],{},"During the first 60 seconds, Docker checks every 3 seconds (Docker Engine 25 and newer), and failures don't count. After that, three failures in a row mark the container unhealthy. Override any of these with ",[262,615,616],{},"healthcheck:"," in your Compose file.",[275,619,621],{"id":620},"what-happens-when-a-check-fails","What happens when a check fails",[258,623,624,625,628,629,521],{},"Docker and Docker Compose only mark a container unhealthy. They don't restart it. Compose uses health only for ",[262,626,627],{},"depends_on"," with ",[262,630,631],{},"condition: service_healthy",[258,633,634],{},"Docker Swarm replaces unhealthy containers. During a rolling update, it waits for each new container to pass before it moves on.",[258,636,637,638,640],{},"Kubernetes ignores Docker's ",[262,639,268],{},". Point a readiness or liveness probe at the same path instead.",[275,642,644],{"id":643},"containers-that-run-another-command","Containers that run another command",[258,646,647,648,651,652,654,655,659],{},"A container that runs ",[262,649,650],{},"php artisan queue:work"," or another command in place of the web server still inherits the image's health check. That check fails, because no web server is running. Give each of these containers its own ",[262,653,616],{},". The ",[365,656,658],{"href":657},"/docs/framework-guides/laravel/health-checks#every-worker-gets-a-check","Laravel health check scripts"," cover the common Laravel workers.",[661,662,663],"style",{},"html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":10,"searchDepth":470,"depth":470,"links":665},[666,667,668,669,670],{"id":277,"depth":470,"text":278},{"id":430,"depth":470,"text":431},{"id":533,"depth":470,"text":534},{"id":620,"depth":470,"text":621},{"id":643,"depth":470,"text":644},"How the built-in Docker health check works in each variation, and how to point it at a route in your app.","md",null,{"head":675,"layout":7},{"title":676},"Health checks - Docker PHP - Server Side Up",true,{"title":96,"description":671},"AEL6OL1_-15GiDgkD74NfZZGpqxbNgsYV-mjzpyQ-H8",[681,683],{"title":142,"path":143,"stem":144,"description":682,"children":-1},"Serve HTTPS from fpm-nginx, fpm-apache, or FrankenPHP with a self-signed certificate, your own certificate, or Let's Encrypt.",{"title":149,"path":150,"stem":151,"description":684,"children":-1},"Get the visitor's real IP address when your app runs behind a CDN, load balancer, or reverse proxy.",1793811939148]