上篇文章介绍了具体的操作步骤,这里总结记录一下部署过程中遇到的问题:
这里注明一下,所有操作容器的命令要在项目目录(tp6)下运行,目录结构如下图:
宿主机(安装宝塔面板)
├─ /www/wwwroot/tp6 (项目目录)
├─app
├─config
├─public
├─vender
... ...
├─think
├─Dockerfile
├─docker-composer.yml
一、Nginx 报 “502 Bad Gateway”
1、排查问题及临时解决方案
步骤1:检查 PHP-FPM 是否正常运行并监听 9003 端口
首先需要找到运行 PHP-FPM 的容器,并确认其内部端口:
执行命令:
#列出所有运行中的容器
[root@iZ2ze8he63z0zt6g8kiae2Z tp6]# docker ps
#输出结果
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7205b7c455d3 tp6-tp6-php-fpm "docker-php-entrypoi…" 7 hours ago Up 7 hours 9000/tcp, 0.0.0.0:9003->9003/tcp, :::9003->9003/tcp tp6-tp6-php-fpm-1
关键信息:
-
容器名称(如
tp6-tp6-php-fpm-1) -
端口映射(如
9003:9000表示宿主机 9003 映射到容器内 9000 端口)
步骤 2:检查容器内 PHP-FPM 是否监听正确端口
进入容器内部,确认 PHP-FPM 实际监听的端口(通常是 9000,而非宿主机的 9003):
# 进入容器(替换容器ID或名称)
[root@iZ2ze8he63z0zt6g8kiae2Z tp6]# docker exec -it tp6-tp6-php-fpm-1 bash
# 在容器内执行,检查PHP-FPM监听端口
root@7205b7c455d3:/var/www/html# netstat -tlnp | grep php-fpm
运行结果:
tcp6 0 0 :::9000 :::* LISTEN 1/php-fpm: master p
根据运行结果,就可以确定Docker内部实际监听的端口是9000
在我们的Docker中,有一段代码如下图红框中部分就是用来修改 PHP-FPM 的监听端口,从默认的 9000 端口改为 9003 端口。
s/listen = 9000/listen = 9003/是替换规则,意思是将所有 "listen = 9000" 字符串替换为 "listen = 9003" ,这里是完全匹配的原则。

再看看容器内的www.conf中的内容,
# 进入容器(替换容器ID或名称)
[root@iZ2ze8he63z0zt6g8kiae2Z tp6]# docker exec -it tp6-tp6-php-fpm-1 bash
//编辑www.conf文件
root@7205b7c455d3:/usr/local/etc/php-fpm.d# vim /usr/local/etc/php-fpm.d/www.conf
如下图:

这里可以看到文件 中是 listen = 127.0.0.1:9000,按照匹配规则,肯定是修改不掉这部分的,所以,我们先临时修改一下(即:进入www.conf文件,修改内容 为 listen = 9003 保存退出)

ctrl + PQ键退出容器
# 重启容器(会自动加载修改后的配置)
[root@iZ2ze8he63z0zt6g8kiae2Z tp6]# docker restart tp6-tp6-php-fpm-1
等待5秒,再次进入容器,检查PHP-FPM监听的端口
# 进入容器(替换容器ID或名称)
[root@iZ2ze8he63z0zt6g8kiae2Z tp6]# docker exec -it tp6-tp6-php-fpm-1 bash
# 在容器内执行,检查PHP-FPM监听端口
root@7205b7c455d3:/var/www/html# netstat -tlnp | grep php-fpm
运行结果:
![]()
还是9000,可能存在多个配置文件:
#容器内直接搜索配置文件中的 listen 配置,查看都有哪些配置文件监听了9000端口
grep -r "listen = " /usr/local/etc/php-fpm.d/
运行结果:

这里看到以.conf结尾的文件有两个一个www.conf,一个是zz-docker.conf,zz-docker.conf文件中监听了9000端口,我们把这个也修改一下试试。
#修改配置文件listen = 9000 为 listen = 9003
vim /usr/local/etc/php-fpm.d/zz-docker.conf
退出容器,重启容器
ctrl + PQ键退出容器
#重启容器
docker restart tp6-tp6-php-fpm-1
等待5秒,再次进入容器,检查PHP-FPM监听的端口
# 进入容器(替换容器ID或名称)
[root@iZ2ze8he63z0zt6g8kiae2Z tp6]# docker exec -it tp6-tp6-php-fpm-1 bash
# 在容器内执行,检查PHP-FPM监听端口
root@7205b7c455d3:/var/www/html# netstat -tlnp | grep php-fpm
运行结果如下图:

监听接口正确了,我们再尝试打开网址,这时候显示404错误。
2、解决方案
前面我们讲述了502错误排查过程,以及临时的解决方案,之所以叫临时解决方案,是因为只要我们删除容器,再次创建我们修改的内容就会被覆盖,并重置为最初的状态。下面我们来尝试从创建容器时便设好监听端口。
方案一:只修改 zz-docker.conf(推荐)
# 基础镜像:PHP 8.1-FPM
FROM php:8.1-fpm
# 使用阿里云镜像源加速
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
# 安装 ThinkPHP6 必需扩展
RUN apt-get update && apt-get install -y \
net-tools \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd pdo_mysql mysqli zip opcache
# 关键修正:只修改 zz-docker.conf(基于你的测试结果)
RUN sed -i 's/listen = 9000/listen = 9003/' /usr/local/etc/php-fpm.d/zz-docker.conf
# 可选:确保 www.conf 不会干扰(注释掉或删除其中的 listen 配置)
RUN sed -i 's/^listen = /;listen = /' /usr/local/etc/php-fpm.d/www.conf
# 配置 PHP 时区
RUN echo "date.timezone = Asia/Shanghai" >> /usr/local/etc/php/conf.d/docker-php-ext-timezone.ini
# 设置工作目录
WORKDIR /var/www/html
# 暴露端口
EXPOSE 9003
方案二:直接创建新的配置文件(最可靠)
FROM php:8.1-fpm
# ... 前面的安装步骤保持不变 ...
# 删除或注释所有现有的 listen 配置,创建统一的配置
RUN sed -i 's/^listen = /;listen = /' /usr/local/etc/php-fpm.d/www.conf && \
sed -i 's/^listen = /;listen = /' /usr/local/etc/php-fpm.d/zz-docker.conf
# 创建新的监听配置
RUN echo '[www]' > /usr/local/etc/php-fpm.d/listen.conf && \
echo 'listen = 9003' >> /usr/local/etc/php-fpm.d/listen.conf && \
echo 'listen.allowed_clients = any' >> /usr/local/etc/php-fpm.d/listen.conf
# ... 后面的配置保持不变 ...
方案三:使用环境变量(Docker 官方推荐方式)
FROM php:8.1-fpm
# ... 前面的安装步骤保持不变 ...
# 确保 zz-docker.conf 使用环境变量(如果它支持)
# 或者直接替换 zz-docker.conf
RUN echo '[www]' > /usr/local/etc/php-fpm.d/zz-docker.conf && \
echo 'listen = 9003' >> /usr/local/etc/php-fpm.d/zz-docker.conf && \
echo 'listen.allowed_clients = any' >> /usr/local/etc/php-fpm.d/zz-docker.conf
# ... 后面的配置保持不变 ...
在前面排查问题时,我们进入容器修改了zz-docker.conf配置文件中的端口方才解决,原因:
官方 PHP-FPM 镜像的
zz-docker.conf是 Docker 环境专用配置,核心内容是:(不同镜像版本会略有不同)
[global] daemonize = no [www] listen = 9000
- 它的优先级高于默认
www.conf即zz-docker.conf加载顺序在最后,会覆盖我们自定义www.conf中的冲突配置,确保监听地址统一 - 若删除该文件,PHP-FPM 会完全依赖你自定义的
www.conf,若你的www.conf中缺少listen相关配置(或格式错误),PHP-FPM 会启动失败或监听地址无效,导致 Nginx 502。我删除了,导致容器无法启动,容器状态如下:

正确的状态:

所以不建议删除。
二、404 错误
1、排查流程
第 1 步:查看日志
docker logs tp6-tp6-php-fpm-1
错误信息 Operation not permitted 表明是文件权限问题,PHP-FPM 进程没有权限读取 /var/www/html/public/index.php 文件
第2步:检查文件权限
index.php是TP的入口文件,如果没有权限肯定是访问不了网页的。下面来检查一下容器内站点文件的权限,代码如下:
docker exec -it tp6-tp6-php-fpm-1 bash
# 检查文件权限和所有者
ls -la /var/www/html/
ls -la /var/www/html/public/index.php
运行结果如图:

从上面的结果来看,index.php文件权限是 755 (-rwxr-xr-x),但文件所有者是 UID 1000(宿主机www用户),而 PHP-FPM 默认以 www-data 用户运行,导致权限不足。
🔍 问题分析
-
当前权限:
-rwxr-xr-x(755) - 权限是足够的 -
文件所有者: UID 1000 (宿主机用户),可以在如主机执行代码
#查询宿主机UID 1000的用户 grep -w "1000" /etc/passwd结果:

-
PHP-FPM 用户: 通常是
www-data(UID 33) 或nobody -
问题: UID 1000 ≠ PHP-FPM 用户,导致
Operation not permitt
第3步:检查容器内当前用户
#进入容器
docker exec -it tp6-tp6-php-fpm-1 bash
#检查容器内当前用户
ps aux | grep php-fpm
运行结果:

🔍 问题分析
-
PHP-FPM Master: 以
root用户运行 -
PHP-FPM Worker: 以
www-data用户运行(UID 33) -
文件所有者: UID 1000(宿主机用户)
-
问题:
www-data用户(UID 33)无法访问 UID 1000 的文件
第4步:修改文件所有者
问题是 www-data 用户(UID 33)无法访问 UID 1000 的文件,那我们将文件所有者改为 www-data。
#进入容器
docker exec -it tp6-tp6-php-fpm-1 bash
#修改容器内文件所有者为www-data
chown -R www-data:www-data /var/www/html/
# 验证修改
ls -la /var/www/html/public/index.php
结果:
![]()
可以打开网址看看是否能正常访问。如果不能继续下一步
第5步:宝塔跨域防护open_basedir 限制
查看容器内文件权限
docker exec -it tp6-tp6-php-fpm-1 ls -la /var/www/html/public/
运行结果:

根据上图,只有.user.ini的权限所有者是root用户,其实没有关系,这里不影响,要是尝试修改也比较麻烦,这个文件是一个特殊文件,所以我们不在修改权限,只修改一下内容。改内容之前,先来解读一下这个文件:
.user.ini 是宝塔面板用于每个站点独立 PHP 配置的文件,类似于 php.ini 的站点级配置。
; 防跨站攻击(open_basedir)
open_basedir = /www/wwwroot/站点目录/:/tmp/:/proc/; 防跨域访问
; 宝塔会自动添加跨域防护规则
关键点:宝塔防跨站攻击里的默认配置使用的宿主机路径,而容器内需要使用容器路径。
这里我在这宿主机路径的基础之上增加了容器路径
open_basedir=/www/wwwroot/tp6/public/:/var/www/html:/tmp/:/proc/
尝试重启容器,之后再访问网站:
#重启容器
docker-compose restart
结果:

2、解决方案
修改 Dockerfile增加文件所有者:
# 基础镜像:PHP 8.1-FPM(与宿主机宝塔 PHP 版本一致,避免语法兼容问题)
FROM php:8.1-fpm
# 使用阿里云镜像源加速
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
# 安装 ThinkPHP6 必需扩展(gd、pdo_mysql 等)
RUN apt-get update && apt-get install -y \
net-tools \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd pdo_mysql mysqli zip opcache
# 修改 zz-docker.conf
RUN sed -i 's/listen = 9000/listen = 9003/' /usr/local/etc/php-fpm.d/zz-docker.conf
# 确保 www.conf 不会干扰
RUN sed -i 's/^listen = /;listen = /' /usr/local/etc/php-fpm.d/www.conf
# 配置 PHP 时区(与宿主机一致,避免时间戳问题)
RUN echo "date.timezone = Asia/Shanghai" >> /usr/local/etc/php/conf.d/docker-php-ext-timezone.ini
# 设置工作目录(与宿主机项目目录对应,后续通过挂载同步代码)
WORKDIR /var/www/html
#关键修正: 递归修改所有者
RUN chown -R www-data:www-data /var/www/html/
# 暴露自定义 PHP-FPM 端口(9003)
EXPOSE 9003
修改部分:
#关键修正: 递归修改所有者
RUN chown -R www-data:www-data /var/www/html/
然后删除并重新创建容器
#删除容器
docker-compose down
#清理网络
docker network prune -f
#清理构建缓存
docker system prune -f
#创建容器
docker-compose build --no-cache
#启动容器
docker-compose up -d
#查看容器
docker-compose ps
宝塔跨域防护open_basedir 限制因为这个导致的错误部分,前边我们修改了宿主机文件,这里重新创建容器也是不会来改变的。
三、补充
1、网站目录设置:一定要设置到public目录下。
2、PHP版本选择“纯静态”
因为我这里依赖于PHP容器,选择纯静态,意思是宿主机不再处理PHP 请求。

暂时补充到这里,如有其他问题,欢迎留言
Docker部署ThinkPHP6常见问题



被折叠的 条评论
为什么被折叠?



