核心是服务名互通、路径对齐、启动有序:PHP连MySQL必须用服务名'mysql'而非'localhost',Nginx中fastcgi_pass须写'php-fpm:9000',volumes统一映射./www:/var/www/html,MySQL需healthcheck,PHP容器须预装mysqli等扩展并显式配置SCRIPT_FILENAME。

用 Docker Compose 编排 PHP、Nginx 和 MySQL,核心不是堆参数,而是让三个容器“说同一种话”——服务名互通、路径对齐、启动有序。
服务名必须一致且用于内部通信
PHP 连 MySQL 不能写 localhost 或 127.0.0.1,得用 mysql;Nginx 转发 PHP 请求时,fastcgi_pass 必须写 php-fpm:9000(前提是服务名定义为 php-fpm)。
- 如果
docker-compose.yml里 MySQL 服务名叫db,PHP 代码中就要用$host = 'db' - Nginx 配置里若写成
fastcgi_pass php:9000,但服务名实际是php-fpm,就会报Connection refused - 所有容器默认在同一个自定义网络(如
app-network)中,靠服务名自动 DNS 解析,无需额外配置
卷映射路径要双向匹配
Nginx 默认根目录是 /usr/share/nginx/html,PHP-FPM 默认工作目录是 /var/www/html。两个容器要共用同一份 PHP 代码,就必须映射到宿主机同一个目录,并各自指向正确路径。
- 推荐统一挂载
./www:/var/www/html:Nginx 配置中设root /var/www/html,PHP-FPM 自然读取该路径 - 若坚持用 Nginx 默认路径,就得同步改两处:
volumes: ./www:/usr/share/nginx/html+ Nginx 配置中root /usr/share/nginx/html - 避免只挂载
./nginx.conf覆盖整个主配置,更安全的是只挂载./nginx/conf.d/default.conf
MySQL 启动就绪不能只靠 depends_on
depends_on 只控制容器启动顺序,不等待 MySQL 完成初始化(比如 mysqld 开始监听 3306 端口)。PHP 容器一启动就连接,大概率失败退出。
立即学习“PHP免费学习笔记(深入)”;
- 给 MySQL 加
healthcheck,例如:healthcheck:<br> test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-prootpass"]<br> timeout: 2s<br> retries: 10
- PHP 容器启动脚本加重试逻辑:
while ! mysqladmin ping -h mysql -u root -prootpass --silent; do sleep 2; done - 或在 PHP 应用层实现连接重试,比依赖容器编排更可控
PHP 容器需预装关键扩展
官方 php:8.2-fpm 镜像默认不含 mysqli、pdo_mysql、mbstring 等常用扩展,直接连 MySQL 会报错。
- 用
build指令自定义镜像,在Dockerfile.php中执行:RUN docker-php-ext-install mysqli pdo_mysql mbstring - 若用现成镜像,确认是否已集成所需扩展,否则运行时会提示
Class 'mysqli' not found - Nginx 的
fastcgi_param SCRIPT_FILENAME必须显式设置,例如:fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;



















