Docker环境下Nginx+PHP7.0-FPM出现502错误,如何排查问题?
咱们先从服务器环境(Nginx+PHP-FPM+Docker)入手,再逐步验证代码逻辑:
一、服务器环境层面排查
1. 确认PHP-FPM是否正常运行
进入你的Docker容器,执行以下命令检查PHP-FPM进程:
ps aux | grep php-fpm
你应该能看到PHP-FPM的主进程和若干子进程。如果没有任何结果,说明PHP-FPM没启动,赶紧看启动日志找原因:
- 查看容器内的PHP-FPM日志:
tail -f /var/log/php7.0-fpm.log - 或者直接看Docker容器日志:
docker logs <你的容器ID>
2. 核对Nginx与PHP-FPM的通信配置
502最常见的原因就是Nginx找不到PHP-FPM的通信端点,重点检查:
- 通信方式(Unix Socket/TCP):
- 如果用Unix Socket:确认Nginx配置里的
fastcgi_pass路径,和PHP-FPM配置(/etc/php/7.0/fpm/pool.d/www.conf)里的listen路径完全一致。比如Nginx里是fastcgi_pass unix:/run/php/php7.0-fpm.sock;,那PHP-FPM的listen也得是这个路径。 - 如果用TCP:确认PHP-FPM的
listen是127.0.0.1:9000(或其他端口),Nginx的fastcgi_pass对应写成127.0.0.1:9000;。
- 如果用Unix Socket:确认Nginx配置里的
- Socket权限:虽然你已经改了,但再确认一次:
执行ls -l /run/php/php7.0-fpm.sock,权限应该是srw-rw---- 1 www-data www-data ...。如果不是,在PHP-FPM的www.conf里设置:
然后重启PHP-FPM:listen.owner = www-data listen.group = www-data listen.mode = 0660service php7.0-fpm restart
3. 修复PATH_INFO无法获取的问题
这个问题虽然不一定直接导致502,但可能影响应用路由,检查Nginx的PHP处理location块里有没有配置:
location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; # 其他fastcgi配置(比如fastcgi_pass、fastcgi_index等) }
确保fastcgi_split_path_info和fastcgi_param PATH_INFO这两行存在,并且放在fastcgi_pass之前。
4. 深挖日志细节
你看到的Nginx日志157#157: *622 recv() failed (104: Connection reset by peer),通常意味着PHP-FPM进程主动断开了连接。此时一定要看PHP-FPM的错误日志,有没有进程崩溃的提示:
比如类似
child 123 exited on signal 11 (SIGSEGV)的日志,说明PHP进程因为代码错误崩溃了,这时候问题就偏向代码层面了。
二、代码层面排查
1. 先做隔离测试:排除ZMQ影响
写一个极简的PHP测试脚本(比如test.php),放在你的web根目录:
<?php phpinfo(); echo "<br>PATH_INFO: " . ($_SERVER['PATH_INFO'] ?? '未设置'); ?>
访问这个脚本,如果仍然返回502,那肯定是服务器环境的问题;如果能正常输出,说明问题出在你的ZMQ相关代码里。
2. 验证ZMQ扩展是否正常加载
在测试脚本里加上一行:
var_dump(extension_loaded('zmq'));
如果返回bool(false),说明ZMQ扩展没安装好,得检查Dockerfile里的安装步骤:是用包管理安装的php-zmq,还是源码编译的?有没有漏掉依赖?
3. 调试ZMQ代码逻辑
如果ZMQ扩展正常,那逐步排查代码:
- 连接有效性:你的应用是ZMQ客户端还是服务端?如果是客户端,确认要连接的ZMQ服务端是否在运行(容器内或外部),地址和端口是否正确。比如连接本地服务的话,用
tcp://127.0.0.1:5555,先确认这个端口有没有进程在监听:netstat -tulpn | grep 5555 - 添加错误处理:给ZMQ相关代码加上try-catch,把错误信息写到日志里:
然后查看PHP错误日志(比如<?php try { $context = new ZMQContext(); $socket = $context->getSocket(ZMQ::SOCKET_REQ); $socket->connect("tcp://127.0.0.1:5555"); $socket->send("测试请求"); $response = $socket->recv(); echo $response; } catch (Exception $e) { error_log("ZMQ错误:" . $e->getMessage()); echo "出错了:" . $e->getMessage(); } ?>/var/log/php/error.log),看有没有连接失败、超时、发送接收异常的信息。
4. 检查PHP运行限制
如果ZMQ操作耗时过长或内存不足,PHP-FPM会直接终止进程,导致连接重置。可以临时调整php.ini的配置:
memory_limit = 256M max_execution_time = 60
重启PHP-FPM后再测试。
三、Docker环境特殊检查
- 启动命令:你的Dockerfile是不是同时启动了Nginx和PHP-FPM?比如用supervisord管理两个进程,或者用
&&串联启动命令?如果只启动了Nginx,没启动PHP-FPM,那肯定502。 - 代码目录权限:确保你的PHP应用代码目录和文件的所有者是
www-data,执行chown -R www-data:www-data /var/www/html(假设你的代码放在这个目录)。
内容的提问来源于stack exchange,提问作者Sheela M




