docker compose本身不适用于高可用生产环境,缺乏服务发现、滚动更新等能力;小项目或过渡期可使用,但须规避mysql认证失败、redis网络不通、nginx 502、php配置不生效等常见陷阱。

直接上生产环境?别急——docker-compose 本身不是为高可用生产编排设计的,它缺服务发现、滚动更新、跨主机调度和健康自动恢复能力。真要上生产,得先确认你是否在用 Swarm 或 Kubernetes;如果只是小项目、内部系统、或过渡期环境,那 docker-compose 可以用,但必须绕开几个关键陷阱。
mysql 容器启动失败:挂载配置后连不上
常见现象是容器反复重启,docker-compose logs mysql 显示 mysqld: Can't read dir of '/etc/mysql/conf.d/' 或 Unknown variable 'default_authentication_plugin'。
- MySQL 8.0+ 默认用
caching_sha2_password插件,老 PHP 客户端(如mysqli扩展未升级)会认证失败,加default_authentication_plugin=mysql_native_password到my.cnf的[mysqld]段 - 挂载
conf.d/目录时,确保宿主机该目录非空且权限为644,否则 MySQL 启动时因读取失败静默退出 - 不要把
data卷挂载到一个已存在且非空的宿主机目录——MySQL 会拒绝初始化,改用干净目录或删掉旧数据再试
php-fpm 无法连接 redis:host 名字写错或端口没暴露
PHP 报错 Connection refused 或 php_network_getaddresses: getaddrinfo failed,基本是网络层不通。
-
redis服务名必须和docker-compose.yml中services下一级 key 完全一致(比如写成redis-server,代码里就得用redis-server,不能写redis) - Redis 容器默认只监听
127.0.0.1,必须在redis.conf里显式设bind 0.0.0.0并关掉protected-mode yes(生产环境需配密码 + 网络隔离) - 如果用了
ports暴露6379,PHP 代码里仍应连redis:6379(走 Docker 内网),而不是localhost:6379(会连宿主机)
nginx 报 502 Bad Gateway:php-fpm socket 路径或权限不匹配
这是最常卡住的点——Nginx 和 PHP-FPM 在两个容器里,不能靠 Unix socket 文件直连,必须走 TCP。
- PHP-FPM 配置里禁用
listen = /run/php/php-fpm.sock,改用listen = 9000(或自定义端口),并设listen.allowed_clients = 0.0.0.0/0 - Nginx 的
fastcgi_pass改成php-fpm:9000(注意 service 名 + 冒号 + 端口),别写127.0.0.1:9000 - 检查 PHP-FPM 的
www.conf是否有user = www-data,而 Nginx 容器里也得用同 UID 用户运行,否则日志里可能看不到错误,只报 502
volume 挂载后 php.ini 不生效:路径和加载顺序搞错了
改了 php.ini 但 phpinfo() 里看不到效果,大概率是文件没被加载,或被后加载的配置覆盖。
- PHP 官方镜像默认从
/usr/local/etc/php/conf.d/加载.ini文件,把你的php.ini放进去并重命名为99-custom.ini(前缀数字保证最后加载) - 不要挂载整个
/usr/local/etc/php/,否则会覆盖conf.d/下的扩展启用文件(如docker-php-ext-enable生成的) - 挂载后进容器执行
php --ini看实际加载路径,再用php -m | grep redis确认扩展是否真启用了
真正容易被忽略的是:MySQL 和 Redis 的持久化卷如果挂载到 NFS 或某些云盘,可能因文件锁或 sync 行为导致启动超时失败;还有 PHP-FPM 的 pm.max_children 在容器里没调,一并发上来就 OOM kill。这些不会报明显错误,只会让服务看起来“偶尔失联”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











