Class 'think\App' not found 根本原因是 vendor/ 目录未正确进入容器,因粗暴挂载(如 ./:/var/www/html)覆盖了构建阶段安装的依赖;必须分离挂载代码与 vendor,或在 Dockerfile 中执行 composer install --no-dev --optimize-autoloader。

为什么 docker-compose up 启动后 PHP 一直报 Class 'think\App' not found
这不是 autoload 没生效,而是 vendor/ 目录根本没挂载进容器 —— ThinkPHP 6.0 的自动加载依赖于 composer autoload 生成的 vendor/autoload.php,而默认的 Docker volume 映射会把宿主机空目录覆盖掉容器内已有的 vendor。
- 别用
./:/var/www/html这种粗暴映射,它会清空容器里原本装好的依赖 - 正确做法是只映射应用代码(
app/、config/、route/等),再把vendor/单独从宿主机复制进去,或在构建阶段composer install - 如果本地没装 Composer,务必在
Dockerfile里执行composer install --no-dev --optimize-autoloader,而不是靠容器启动时临时拉包(网络不稳定极易失败)
MySQL 连不上?检查 database.php 里的 hostname 别写 127.0.0.1
Docker 容器间通信走的是自定义网络,默认不能用 localhost 或 127.0.0.1 访问其他服务 —— ThinkPHP 配置里写 'hostname' => '127.0.0.1',实际连的是 PHP 容器自己的 loopback,不是 MySQL 容器。
- 必须改成
'hostname' => 'mysql'(前提是docker-compose.yml中 service 名为mysql) - TP6 的
.env文件支持DB_HOST=mysql,但要注意:环境变量优先级高于配置文件,如果database.php里硬编码了127.0.0.1,.env 就无效 - 加个健康检查:
php think migrate:status能跑通,才说明 DB 连接和 PDO 扩展都正常
docker-compose.yml 里要不要配 restart: unless-stopped?
要,但仅对 mysql 和 redis 这类状态服务开,PHP-FPM 或 Nginx 进程不该自动重启 —— ThinkPHP 的 runtime/ 目录若被反复重建,会导致缓存、日志、session 全丢,反而掩盖真实错误。
- PHP 服务建议设
restart: no,靠开发时手动docker-compose restart php触发热更新 - MySQL 必须加
restart: unless-stopped,否则宿主机重启后数据库挂起,TP6 连接池会卡住几秒甚至超时 - 注意 volume 权限:
mysql容器的数据目录映射到宿主机时,宿主机用户 UID 必须和容器内mysql用户一致(通常是 999),否则容器起不来,日志只报Permission denied不说具体哪个文件
前端资源怎么热更新?别碰 public/ 里的 JS/CSS
ThinkPHP 6 默认不处理前端构建流程,public/ 是静态资源出口,但直接改这里无法触发 webpack/vite 热更新 —— 新人常把 vite 构建产物手动拷进 public/,结果改了源码却看不到效果。
立即学习“PHP免费学习笔记(深入)”;
- 开发时让 vite 在宿主机跑
vite dev,通过反向代理把/static/请求转发到http://localhost:3000/(Nginx 配置里加location /static { proxy_pass http://host.docker.internal:3000; }) - 生产构建仍走
vite build输出到public/static/,由 Nginx 直接 serve,不经过 PHP - TP6 的
Asset::url()生成路径要和实际部署结构一致,比如Asset::url('static/js/app.js')对应public/static/js/app.js,别漏掉static/前缀
vendor/ 怎么进容器、DB_HOST 写什么、谁该重启谁不该重启、前端资源走哪条路——每个环节断掉,都会卡住新人一上午。



















