ThinkPHP 容器化部署的核心是将 Web 根目录限定为 public 目录,并在 Docker 构建阶段完成 Composer 依赖安装,同时单独挂载 runtime 目录解决权限问题。
先说结论:ThinkPHP 容器化成功的关键在于构建阶段预装依赖、运行时权限对齐以及 Web 服务器正确配置伪静态。
- 适合 ThinkPHP 6/8 及需要环境一致性的生产部署场景
- 先准备 Dockerfile 分层构建策略与 Nginx 伪静态配置
- 验收时检查 runtime 写入权限与路由跳转是否正常
命令速用版
以下是 Dockerfile 关键片段与 Nginx 配置核心指令,可直接用于构建与配置。
Dockerfile 关键指令:
RUN mkdir -p /var/www/runtime && chmod -R 777 /var/www/runtime
RUN composer install `--no-dev` `--optimize-autoloader`
Nginx location 配置:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
}为什么会这样
容器启动失败通常是因为自动加载文件缺失或目录权限不匹配,而非框架代码错误。
ThinkPHP 依赖 vendor/autoload.php 进行类加载,若 Docker 构建时未执行 composer install,容器内 vendor 目录为空,导致 Class 'think\App' not found 错误。runtime 目录用于存放缓存与日志,若宿主机挂载目录的 UID 与容器内 www-data 用户不一致,PHP 进程无法写入文件,引发 Permission denied 错误。Nginx 默认不传递 PATH_INFO,若未配置 fastcgi_split_path_info,ThinkPHP 路由无法解析伪静态 URL。
分步处理
按以下步骤完成镜像构建与容器编排,确保依赖、权限与路由配置正确。
1. 编写 Dockerfile 分层构建
先复制 composer 配置文件安装依赖,再复制代码,避免代码变更触发依赖重装。在构建阶段创建 runtime 目录并赋予权限,不要依赖容器启动时的 chown 命令。
COPY composer.json composer.lock ./ RUN composer install `--no-dev` `--optimize-autoloader` COPY . . RUN mkdir -p /var/www/runtime && chmod -R 777 /var/www/runtime
2. 配置 Docker Compose 挂载
将 public 目录挂载为 Web 根目录,runtime 目录单独挂载为可写,.env 文件挂载至项目根目录而非 public 子目录。
volumes: - ./public:/var/www/html:ro - ./runtime:/var/www/runtime:rw - ./.env:/var/www/.env
3. 配置 Nginx 伪静态
root 指向 public 目录,location 块中补充 PATH_INFO 参数,确保 ThinkPHP 路由能获取完整路径信息。
root /var/www/html/public;
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}怎么验证是否生效
通过容器内文件检查与页面访问测试,确认依赖加载与权限配置无误。
1. 检查依赖文件
进入容器执行 ls -l vendor/autoload.php,确认文件存在且非空。若文件缺失,说明构建阶段未成功执行 composer install。
2. 验证环境变量
在容器内运行 php think env:show 或 php -r "var_dump(\think\Env::get('app.debug'));",确认.env 文件已被正确加载。
3. 测试路由与写入
访问非首页路由如 /index.php/user/login,确认不报 404。查看 runtime/log 目录是否有新日志文件生成,确认权限写入正常。
常见坑
以下场景容易导致部署失败,操作时需特别注意权限隔离与配置细节。
- UID 不一致:宿主机与容器内 www-data 用户 ID 不同会导致挂载目录不可写,建议在 Dockerfile 中显式 chmod 777 而非 chown。
- Web 根目录错误:Nginx root 必须指向 public 目录,若指向项目根目录会导致 app 等敏感目录暴露。
- PATH_INFO 丢失:Nginx 未配置 fastcgi_split_path_info 会导致 ThinkPHP 路由失效,所有请求 fallback 到首页。
- 多实例缓存冲突:多个容器共用同一 runtime 目录会导致缓存错乱,每个实例应独立挂载 runtime 目录。
常见问题
Class 'think\App' not found 怎么解决?
原因是 Composer 自动加载文件未生成,需在 Dockerfile 构建阶段执行 composer install `--no-dev` `--optimize-autoloader`。
Nginx 配置后路由依然 404 怎么办?
检查 location 块是否缺少 fastcgi_param PATH_INFO $fastcgi_path_info;,且 root 是否指向了 public 目录。
runtime 目录报错 Permission denied 如何处理?
避免在容器启动时 chown,应在 Dockerfile 中创建目录并 chmod 777,或确保挂载时宿主机目录权限与容器用户一致。
参考来源
- 一键部署上线:thinkphp 使用 Docker 容器化【DevOps】
- Docker 容器化搭建 ThinkPHP 运行环境:一键部署与迁移指南【教程】
- ThinkPHP 怎么上 Docker_ThinkPHP 容器化部署解答【汇总】
- ThinkPHP 项目结构如何适应容器化部署_Docker 目录挂载实践
- ThinkPHP 如何使用 Docker 部署
- ThinkPHP 在 Docker 中如何快速部署_容器化环境搭建与镜像构建
- ThinkPHP 项目在 Docker 容器中的部署优化_高性能容器化环境配置
- ThinkPHP 的 Docker 部署怎么做?ThinkPHP 如何容器化运行?
- ThinkPHP 伪静态怎么配 Docker_ThinkPHP 多语言容器化部署说明【教程】
- 使用 Docker 部署 Thinkphp8 环境