Yii容器化核心卡点在PHP扩展、Web服务路径、数据库网络三处,缺一则500或Connection refused:需显式安装pdo_mysql/mbstring等扩展;Apache/Nginx须正确配置DocumentRoot和重写规则;数据库host必须用服务名如'db'而非localhost。

Yii 容器化不是“装个镜像就能跑”,核心卡点在 PHP 扩展、Web 服务路径、数据库网络三处,漏一个就 500 或 Connection refused。
PHP 扩展缺失导致容器启动失败
容器里 php -v 能跑,但 Yii 启动报错“Class 'PDO' not found”或“mbstring extension is not loaded”,说明基础扩展没装全。官方 php:8.2-apache 镜像默认只带最简扩展,Yii 2.x 至少要 pdo_mysql、mbstring、xml;Yii 3.x 还强依赖 json 和 ctype。
- 别用
alpine镜像起步——pdo_mysql编译容易卡在libmysqlclient,调试成本高 - Dockerfile 里必须显式安装并启用:
RUN docker-php-ext-install pdo pdo_mysql mbstring xml ctype json && docker-php-ext-enable pdo pdo_mysql mbstring xml ctype json - 进容器执行
php -m | grep -E 'pdo|mbstring|json'快速验证,比看日志快 - 检查
phpinfo()输出的Loaded Configuration File路径,确保你改的是它,不是镜像里只读的副本
Apache/Nginx 没把请求转发给 index.php
浏览器打开是 403、404 或直接下载 index.php 源码,问题不在代码,而在 Web 服务器没识别 Yii 的入口逻辑。Yii 2.x 默认靠 web/.htaccess 重写 URL,但官方 PHP-Apache 镜像默认禁用 AllowOverride;Nginx 则需要手动配 fastcgi_pass 和 try_files。
- Apache 场景:在虚拟主机配置里,
DocumentRoot必须指向/var/www/html/web(Yii 2)或/var/www/html/public(Yii 3),不能是项目根目录 -
<directory></directory>块里必须有AllowOverride All和Require all granted - Nginx 场景:确认
location /块里有try_files $uri $uri/ /index.php?$args;,且fastcgi_pass指向 PHP-FPM 服务名(如php:9000) - 删掉
web/下空的.htaccess——如果mod_rewrite没加载,它反而触发 500,而 Docker 默认不暴露 Apache 错误日志
数据库连接写 localhost 导致 Connection refused
本地开发时 'host' => 'localhost' 没问题,一进容器就报 SQLSTATE[HY000] [2002] Connection refused,因为容器内 localhost 指自己,不是宿主机或数据库容器。
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
-
docker-compose.yml 里数据库服务名是
db,Yii 配置里就得写'host' => 'db',别用环境变量拼接字符串,容易引号逃逸 - 加健康检查:在
db服务里配healthcheck(比如mysqladmin ping -h localhost -u root -proot),然后app服务用depends_on: { db: { condition: service_healthy } } - 调试时别只看 Yii 报错——进 PHP 容器直接执行
nc -zv db 3306,秒级确认网络连通性 - runtime 目录权限常被忽略:
runtime和assets必须属主为www-data(Apache)或www-data/nginx(Nginx),否则写缓存失败也会 500
开发 vs 生产的镜像构建差异
同一个 Dockerfile 不能通吃开发和生产。开发要挂载代码、开 Xdebug;生产要删 dev 依赖、关调试、用非 root 用户运行。
- 多阶段构建更安全:
composer install --no-dev --optimize-autoloader放构建阶段,运行阶段只 COPYvendor/和代码,体积小、攻击面小 - 开发环境用 volume 挂载:
volumes: - ./:/app,但注意runtime目录不能被覆盖,得单独挂载或设 chmod - 生产镜像里删掉
xdebug、opcache.enable_cli=0关 CLI 缓存,user www-data显式降权 -
.dockerignore必须包含vendor/、.git、tests/、docker-compose.yml,避免无谓 COPY 拖慢构建
真正难的不是写完 docker-compose.yml,而是每次改配置后,能不能在 30 秒内判断是 PHP 扩展问题、Web 路由问题,还是 Docker 网络问题——关键在分层验证:先 php -m,再 curl -I http://localhost,最后 nc -zv db 3306。










