Docker同容器部署Nginx+PHP-FPM访问报502/404错误排查
问题根因
两个阶段的报错属于独立配置错误,无直接关联:
- 初始阶段单次curl触发上百条/index.php 502错误日志:Nginx配置中存在两个匹配
.php后缀的location块,其中反向代理到127.0.0.1:80的规则会将PHP请求重新发回Nginx自身监听端口,请求在两个location规则间反复跳转形成死循环,直到触发Nginx内部递归请求上限返回502,因此产生大量重复日志记录。 - 注释冗余location块后出现的
404 Not Found、Primary script unknown错误:本质是PHP-FPM无法定位、读取Nginx通过FastCGI传递的脚本文件,和你已修改的站点目录权限操作无直接关系,核心诱因有两点:- FastCGI参数配置错误:
fastcgi_param SCRIPT_FILENAME未传递容器内的脚本绝对路径,比如配置为相对路径、Nginx设置的站点根目录与PHP-FPM识别的路径不一致 - 进程运行用户不匹配:
nginx:stable-alpine镜像默认Nginx运行用户为nginx,但apk源安装的PHP-FPM默认运行用户为nobody,即使将/usr/share/nginx/html目录权限修改为nginx属主,nobody身份运行的PHP-FPM依然没有站点文件读取权限,直接触发脚本找不到的报错。
- FastCGI参数配置错误:
修复方案
严格遵循同容器部署、不使用supervisor管理进程的约束,按以下步骤调整即可:
1. 精简Nginx配置
删除代理到127.0.0.1:80的冗余.php匹配location块,配置FastCGI时明确传递绝对路径参数,参考可用配置如下:
server { listen 8080; server_name localhost; # 站点根目录可沿用原有/usr/share/nginx/html,只要和后续权限配置、PHP-FPM配置保持路径一致即可 root /usr/share/nginx/html; index index.php index.html; location / { try_files $uri $uri/ =404; } # 仅保留这一个.php请求匹配规则 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; # 核心配置:必须传递脚本绝对路径给PHP-FPM fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
2. 对齐Nginx与PHP-FPM运行用户
找到PHP-FPM的进程配置文件(Alpine系统下默认路径为/etc/php<你的PHP版本号>/php-fpm.d/www.conf,比如安装PHP82则路径为/etc/php82/php-fpm.d/www.conf),修改以下配置项,和Nginx运行用户保持一致:
user = nginx group = nginx listen.owner = nginx listen.group = nginx
配置完成后重新递归设置站点目录权限,不要使用777权限:chown -R nginx:nginx /usr/share/nginx/html && chmod -R 755 /usr/share/nginx/html
3. 调整entrypoint.sh启动逻辑
不使用进程管理工具时,需要保证两个进程正常运行,同时让Nginx作为容器1号进程接收系统信号,避免容器异常退出,参考脚本如下:
#!/bin/sh # 后台启动PHP-FPM php-fpm -D # 前台启动Nginx,占据主进程位置 nginx -g 'daemon off;'
执行chmod +x entrypoint.sh给脚本添加执行权限。
4. 验证
重新构建镜像、启动容器后,执行curl -i http://localhost:8080即可正常获取index.php的响应内容,不会再出现死循环502或File not found报错。
避坑提示:不要为了快速解决权限问题将Nginx、PHP-FPM改为root用户运行,违反容器最小权限原则,存在安全风险。
内容的提问来源于stack exchange,提问作者Sibtain
相关产品推荐
相关产品推荐

