ThinkPHP Docker部署需手动安装PDO、mbstring等扩展,分离COPY源码路径避免覆盖runtime,启用Apache mod_rewrite并允许.htaccess,Nginx+PHP-FPM需对齐通信地址与依赖顺序。

ThinkPHP项目Docker打包时PHP扩展缺失怎么办
直接跑不起来,报 Class 'PDO' not found 或 mbstring extension is required —— 这不是代码问题,是镜像里根本没装扩展。
ThinkPHP 6+ 默认依赖 pdo_mysql、mbstring、openssl、curl、json(PHP 8+ 还要 ctype),但官方 php:8.2-apache 镜像只带最精简的扩展集。
- 在
Dockerfile的RUN阶段用docker-php-ext-install手动启用:比如docker-php-ext-install pdo mbstring opcache - 如果要用 MySQLi 而非 PDO,还得加
mysqli;用 Redis 就得额外pecl install redis+docker-php-ext-enable redis - 别在
php.ini里靠extension=行去“加载”未编译的扩展,那只会报unable to load dynamic library -
gd扩展需要先apt-get install -y libfreetype6-dev libjpeg-dev libpng-dev,再docker-php-ext-configure gd --with-freetype --with-jpeg
Dockerfile中COPY ThinkPHP源码的路径和时机怎么选
常见错误是把整个项目 COPY . /var/www/html,结果 runtime/ 目录被覆盖,缓存写失败,或者 .env 文件被硬编码进镜像,暴露数据库密码。
ThinkPHP 的 public/ 是 Web 入口,其他目录(app/、config/、runtime/)应按角色分离处理:
立即学习“PHP免费学习笔记(深入)”;
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- 只
COPY public/ /var/www/html/,然后用VOLUME ["/var/www/html/runtime"]显式声明运行时挂载点 -
config/和app/等业务代码,建议COPY app/ /var/www/app/+COPY config/ /var/www/config/,再通过index.php中修改define('APP_PATH', '/var/www/app/')指向新路径 -
.env绝对不要 COPY 进镜像;改用 Docker--env-file或environment:在docker-compose.yml中注入 - 避免
COPY .,否则每次构建都会让中间层缓存失效,哪怕只改了一行日志配置
Apache + ThinkPHP 的 URL 重写(Rewrite)在容器里不生效
访问 /index.php/user/login 可以,但去掉 index.php 就 404 —— 不是 ThinkPHP 配置问题,是 Apache 没开 mod_rewrite 或没允许 .htaccess 覆盖。
官方 php:8.2-apache 镜像默认禁用 AllowOverride,且 mod_rewrite 虽已安装但未启用。
- 在
Dockerfile中加RUN a2enmod rewrite - 覆盖 Apache 默认站点配置:用
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf,其中关键段落必须包含:<Directory "/var/www/html">AllowOverride AllRequire all granted</Directory> - ThinkPHP 自带的
public/.htaccess只需保留,无需改动;确认它确实被 COPY 进了/var/www/html/ - 别用
httpd.conf方式配置,Debian 系 Apache(镜像用的)优先读sites-available/下的配置
为什么 docker-compose up 后 PHP-FPM 日志全空,但页面一直 502
不是 Nginx 报错,也不是 ThinkPHP 报错,而是 PHP-FPM 根本没起来,或监听地址不对 —— 容器间网络和 socket 路径最容易出错。
ThinkPHP 项目若拆成 Nginx + PHP-FPM 两个容器(推荐),通信必须显式对齐:
- Nginx 配置里
fastcgi_pass必须写成php-fpm:9000(对应docker-compose.yml中 service 名),不能写127.0.0.1:9000或localhost:9000 - PHP-FPM 容器要暴露
9000端口,或更稳妥地用 Unix socket:listen = /var/run/php/php8.2-fpm.sock,然后通过volumes共享该 socket 文件路径 - 检查 PHP-FPM 日志:默认输出到
stderr,所以docker logs <php-fpm-container>才能看到启动失败原因(比如unable to bind listening socket) - 别忽略
pm.max_children设置过小导致并发一高就拒绝连接,这也会表现为 502 且无明确日志
最常漏掉的是 PHP-FPM 容器没设 depends_on 或健康检查,导致 Nginx 启动时 PHP-FPM 还没 ready,第一次请求就永久卡住。这个点没有错误提示,只有反复刷新才偶然成功。


















