必须显式声明自定义bridge网络,因docker 2026默认行为变更,未定义networks将回退legacy bridge模式,导致php容器无法通过服务名mysql解析地址而报connection refused;fastcgi_pass须填服务名php:9000而非localhost,且php需监听0.0.0.0:9000;还需统一uid权限并挂载/dev/shm以保障opcache性能。

直接用 docker-compose.yml 定义 nginx、php、mysql 三服务并绑定自定义网络,是构建真正隔离 PHP 环境的唯一可靠方式。单容器跑全栈或靠 localhost 通信,必然在跨服务调用、权限、缓存、时区上出问题。
为什么必须显式声明 networks: default: driver: bridge
不写 networks 块,Docker 会 fallback 到 legacy bridge 模式,导致 php 容器无法通过服务名 mysql 解析数据库地址——你看到的 Connection refused 或 php_network_getaddresses: getaddrinfo failed 大多源于此。
-
default网络名可以省略,但driver: bridge必须显式写出,否则 Docker 2026 默认行为已变更 - 所有服务必须落在同一自定义网络下,
depends_on只控制启动顺序,不解决 DNS 解析 - 若需多项目共存,每个项目应使用独立网络名(如
project-a-net),避免服务名冲突
fastcgi_pass php:9000 中的 php 是服务名,不是容器名或 IP
Nginx 配置里写 fastcgi_pass localhost:9000 或 127.0.0.1:9000 一定失败——Nginx 和 PHP-FPM 在不同容器里,localhost 指的是 Nginx 自己的环回接口,根本连不到 PHP 容器。
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
-
fastcgi_pass后必须填docker-compose.yml中php服务的 name,例如fastcgi_pass php:9000 - 确保 PHP 容器监听
0.0.0.0:9000(默认行为),而非127.0.0.1:9000;Alpine 镜像中部分版本会默认 bind 到本地,需检查www.conf的listen行 - 如果用
php:8.3-fpm-alpine,默认 listen 地址是9000,等价于0.0.0.0:9000,无需额外改
PHP 容器挂载代码时必须处理 UID 权限一致性
宿主机用户 UID 和容器内 www-data UID 不一致,会导致 opcache 缓存目录不可写、日志生成失败、composer install 报 Permission denied。
- 在
php服务中加user: "1001:1001"(与宿主机开发用户 UID/GID 一致),再配合chown -R 1001:1001 /var/www/html初始化权限 - 不要依赖
root用户启动 PHP-FPM,2026 年多数安全策略已禁止非特权容器以 root 运行 - 若用 Alpine 镜像,
www-data用户默认 UID 是 82,和常见 Linux 发行版(UID 33)不匹配,硬编码 UID 更稳妥
OPcache 预热必须配合 /dev/shm 共享内存挂载
只开 opcache.enable=1 不够,冷启动时首次请求仍慢;更糟的是,Alpine 默认没挂载 /dev/shm,OPcache 会退化为文件缓存,性能掉一半。
- 在
php服务中加volumes: - /dev/shm:/dev/shm,让 OPcache 使用 tmpfs 内存段 -
opcache.preload文件路径必须是绝对路径,且需在容器启动前存在;推荐把preload.php放进镜像,而非挂载 - 验证是否生效:访问
index.php后执行php -r "print_r(opcache_get_status());",看memory_usage是否增长、preloaded_scripts是否有值
最常被跳过的其实是 /dev/shm 挂载和 UID 对齐——这两个点不处理,环境看似跑起来了,但一上真实流量就暴露缓存失效、日志丢写、定时任务卡死等问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










