thinkphp 6/7 项目 docker 部署推荐 nginx 与 php-fpm 同容器运行,避免跨容器导致的 path_info 丢失、静态资源 404 和路由解析异常;需正确配置 script_filename、挂载 runtime 目录、启用 opcache,并验证路由缓存与环境变量加载。

直接上结论:ThinkPHP 6/7 项目用 Docker 部署完全可行,但不能照搬 Laravel 或 Symfony 的 Nginx+PHP-FPM 分容器方案——默认的 public/index.php 入口 + 单点路由模式,更适合「Nginx 和 PHP-FPM 同容器」的轻量结构,否则容易因跨容器网络、静态资源路径、PATH_INFO 传递失败导致 404 或路由解析异常。
为什么 ThinkPHP 容器化要避免“标准三件套”分拆
ThinkPHP 默认依赖 PATH_INFO 或 QUERY_STRING 解析 URL 路由(如 /index/user/list),而当 Nginx 和 PHP-FPM 分属不同容器时:
- Nginx 容器需通过
fastcgi_pass指向 PHP-FPM 容器的host.docker.internal:9000或自定义网络别名,但 Alpine 基础镜像常默认禁用host.docker.internal,手动配置易漏 - PHP-FPM 容器若未显式设置
fastcgi_param SCRIPT_FILENAME指向挂载路径下的真实文件(如/var/www/public/index.php),就会报File not found - ThinkPHP 的
__ROOT__和静态资源路径(CSS/JS)在多容器下易因 Nginx 根目录与 PHP 工作目录不一致而 404 - 调试时
docker logs -f nginx-container看不到 PHP 错误,得切两个容器查日志,效率低
推荐结构:单容器内 Nginx + PHP-FPM + Supervisord
这不是“反模式”,而是 ThinkPHP 开发/测试/预发布环境最稳的落地方式。Alpine 镜像体积小、启动快,Supervisord 能统一管理两个进程并自动拉起崩溃的子服务。
关键配置点:
MiniMax 图片理解 + 网络搜索 MCP 工具。适配 Docker 环境(极空间等),支持图片 OCR 识别、图像内容理解、网络搜索。API Key 安全存储在本地 credentials 文件,不暴露在代码中。
- Dockerfile 中用
FROM php:8.3-fpm-alpine为基础,再apk add nginx;不要用nginx:alpine反向安装 PHP 扩展——PHP 模块兼容性难控 - 必须启用
php.ini中的enable_dl = On和extension=opcache,否则 ThinkPHP 的模板编译和路由缓存会失效 - Supervisord 配置里,
nginx要设autostart=true,php-fpm设startsecs=0(避免因 FPM 启动慢导致 Nginx 报connect refused) - Nginx server 块中,
root /var/www/public必须与location ~ \.php$内的fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name严格匹配
挂载代码时必须避开的三个路径陷阱
ThinkPHP 对运行时目录敏感,挂载不当会导致 runtime 权限错误、缓存写入失败、甚至容器反复重启:
- 不要只挂载
./src:/var/www—— 这会让/var/www/runtime成为只读 bind mount,PHP 写入失败。应单独挂载./src/runtime:/var/www/runtime并加:rw -
.env文件必须挂载到/var/www/.env,且宿主机权限设为644;若用docker run -e注入变量,ThinkPHP 6.3+ 的Env类默认不读取环境变量,仍会 fallback 到文件 - Alpine 镜像默认无
procps,top、ps命令不可用,调试内存占用时docker stats是唯一可靠手段,别指望进容器跑htop
上线前必验的 ThinkPHP 特定检查项
很多问题只在容器里暴露,本地开发根本看不出:
- 执行
docker exec -it tp-app php think optimize:route,确认输出 “Route cache updated successfully”,否则路由全 404 - 访问
/index.php?s=/index/test(显式带s=参数)能通,但/index/test404?检查 Nginx 的try_files $uri $uri/ /index.php?s=$uri&$args是否漏了&或引号包裹 - 上传文件失败?确认
php.ini中upload_max_filesize = 20M和post_max_size = 22M已生效,且容器内/tmp目录可写(Alpine 默认可写,但若挂载了宿主机/tmp就可能受限) - 使用 Redis 缓存时报 “Connection refused”?不是密码错,是容器没连对网络——用
docker network inspect tp-net确认 Redis 容器 IP,并在.env里写死该 IP,别用redis这个 hostname(除非你建了自定义 bridge 网络并指定了 alias)
真正麻烦的从来不是写 Dockerfile,而是 ThinkPHP 在容器里对路径、权限、环境变量的隐式强依赖——它不像 Laravel 那样把所有配置抽象成 config/ 下的数组,很多行为直读 $_SERVER 和文件系统。部署前多跑一遍 php think env 和 php think version,比盲目改 Nginx 配置有用得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










