Docker健康检查必须用curl而非wget,因FrankenPHP容器默认不含wget;需用curl -f确保非2xx时返回非零码,路径固定为/health,且须expose 8000端口、合理设置timeout(≥10s)、start-period(≥60s)等参数防误判。

healthcheck 指令必须用 curl 而不是 wget
FrankenPHP 容器默认不带 wget,只含 curl。直接写 wget --spider http://localhost:8000/health 会失败,健康检查始终报 unhealthy。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 用
curl -f http://localhost:8000/health:-f 确保 HTTP 非 2xx 时返回非零退出码 - 避免加
-s(静默)或-o /dev/null:Docker 健康检查依赖命令退出状态,不关心输出内容 - 路径必须是
/health:FrankenPHP 内置健康端点固定为该路径,不可自定义(除非改源码)
timeout 和 interval 设置不当会导致假死判断
FrankenPHP 启动时需加载 PHP 应用、编译字节码,首请求可能耗时 >10s。若 healthcheck.timeout 设太短(如 5s),容器还没 ready 就被标记 unhealthy,进而触发重启循环。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
-
interval: 30s(最低推荐):避免高频探测压垮刚启动的进程 -
timeout: 10s:足够覆盖冷启动延迟,又不会让故障响应过慢 -
start_period: 60s:给容器留足初始化窗口,60s 内的 unhealthy 不计入失败计数 -
retries: 3:连续 3 次失败才判为 unhealthy,防偶发网络抖动误判
需要显式暴露 8000 端口才能 curl 通
Docker 默认隔离网络,即使容器内 curl http://localhost:8000/health 能通,也不代表健康检查能通——因为 healthcheck 是在宿主机命名空间里执行的 shell 命令,走的是容器的 localhost 接口,而该接口仅当端口被 expose 或 ports 显式声明后才对内部 loopback 可达。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 必须在 service 下写
expose: ["8000"](推荐)或ports: ["8000:8000"] - 不能只靠 FrankenPHP 的
--server参数监听 0.0.0.0:8000 就认为“已开放”:Docker 层不感知应用层绑定 - 验证方式:进入容器
docker exec -it frankenphp sh -c "curl -f http://localhost:8000/health"成功,且docker-compose ps显示healthy,才算配置闭环
PHP 应用未就绪时 /health 返回 503 是正常行为
FrankenPHP 的 /health 端点不只是检查自身进程存活,还会尝试执行一个最小 PHP 上下文(比如 require_once 一次 bootstrap)。如果 public/index.php 依赖的扩展没装、.env 缺失或数据库连接失败,它会直接返回 503,而不是 200。
这意味着:
- 健康检查失败不一定是 FrankenPHP 问题,大概率是你的 PHP 应用启动卡住了
- 别急着调
healthcheck参数,先看docker-compose logs frankenphp末尾是否有Fatal error或Connection refused - 临时调试可把健康检查改成
curl -f http://localhost:8000/(首页),但上线前务必切回/health:首页可能缓存或跳转,不具备幂等性和语义准确性



















