先查 Traefik 日志确认是否代理层报错:执行 docker logs traefik,重点排查 500、connection refused、no healthy endpoints、timeout 等关键词;若日志显示请求未到达后端,则问题在 Traefik 配置或网络,而非 PHP 应用本身。

查看 traefik 日志确认是否是反向代理层报错
500 错误不一定是 PHP 应用本身的问题,traefik 作为反向代理,可能在转发请求时就失败了。先执行 docker logs traefik(或你实际的 traefik 容器名),重点看是否有类似 status code 500、connection refused、no healthy endpoints 或 timeout 的日志。
常见误导点:浏览器显示 500,但 traefik 日志里根本没打到后端,说明请求压根没进 PHP 容器——这时候查 PHP 日志毫无意义。
- 如果日志里有
upstream connect error or disconnect/reset before headers,大概率是 PHP 容器没起来、端口没暴露、或健康检查失败 - 如果看到
retrying upstream request后跟 500,说明 traefik 尝试了多个后端都失败,需检查服务发现配置(如 labels 是否写错) - traefik v2+ 默认不透传后端响应头,若 PHP 返回了带错误信息的
X-PHP-Response-Code,traefik 不会显示它——得进容器看原始响应
进入 PHP 容器验证服务是否真正响应
绕过 traefik 直接 curl PHP 应用内部地址,是最直接的验证方式。假设你的 PHP 容器名为 php-app,监听 8000 端口:
docker exec -it php-app curl -v http://localhost:8000/index.php
观察返回状态码和 body 内容。如果这里也返回 500,问题就在 PHP 层;如果返回 200,那一定是 traefik 配置或网络策略出了问题。
立即学习“PHP免费学习笔记(深入)”;
- PHP 容器内执行
netstat -tlnp | grep :8000,确认服务确实在监听且没被 bind 到127.0.0.1(应为0.0.0.0) - 检查
php-fpm.conf中的listen.allowed_clients,Docker 网络下常需设为0.0.0.0/0或注释掉 - 若用 Apache,确认
DocumentRoot路径正确,且.htaccess没触发重写死循环(会导致 500)
检查 PHP 错误是否被静默吞掉
很多 Docker 镜像默认关闭 display_errors,导致 PHP 报错不输出,traefik 收不到完整响应体,直接返回 500。别只看浏览器,要查 PHP 的错误日志。
在 PHP 容器中运行:tail -f /var/log/php/error.log(路径依镜像而异,常见还有 /proc/1/fd/2 或 /dev/stderr);或者临时加一行到入口脚本顶部:
ini_set('display_errors', '1'); ini_set('log_errors', '1');
-
error_log = /var/log/php/error.log必须在php.ini中显式设置,否则某些镜像不写日志 - 常见触发点:
require不存在的文件、扩展未加载(如mysqli)、memory_limit耗尽、opcache编译失败 - 如果日志里出现
PHP Fatal error: Out of memory,不是代码问题,而是容器内存限制太低,需调高mem_limit
确认 traefik 动态配置与 PHP 服务标签匹配
traefik v2+ 依赖容器 labels 做自动路由,一个字母写错就会导致 500(因为找不到后端)。检查你的 docker-compose.yml 中 PHP 服务的 labels 是否和 traefik 的 entryPoints、routers、services 对应。
典型错误示例:traefik.http.routers.php.rule=Host(`app.local`) 但本地 hosts 没配,或 rule 写成 Host(app.local)(缺引号);又或者 traefik.http.services.php.loadbalancer.server.port=9000,但 PHP 实际监听的是 8000。
- 确保
traefik.enable=true在 PHP 服务下,而不是整个 compose 文件顶层 - 如果用了自定义中间件(如 auth、redirect),先临时移除,确认是否中间件逻辑抛异常导致 500
- traefik v2.10+ 对 label 名称更严格,
traefik.http.routers.php.tls若没配证书会静默失败,可加tls=false显式关闭测试
最省事的验证法:把 traefik 的 dashboard 打开(/dashboard/),看 routers 列表里对应服务的状态是不是 enabled,后端 endpoints 是不是绿色健康——如果不是,配置肯定有硬伤。











