容器内连不通 MySQL,90% 是网络层没通,不是 Hyperf 配置错了;需先 ping 数据库地址验证连通性,再检查 Docker 网络模式、端口开放、DB_HOST 填写规则及协程连接池参数。

容器内连不通 MySQL,90% 是网络层没通,不是 Hyperf 配置错了。先确认容器能 ping 通数据库地址,再调协程客户端参数。
容器网络连通性怎么验证
Hyperf 运行在容器里时,localhost 指的是容器自身,不是宿主机或另一台数据库服务器。常见错误是把 DB_HOST=localhost 当成“本机数据库”,结果连的其实是空容器。
- 用
docker exec -it <hyperf-container> sh进入容器,执行ping -c 3 <mysql-host>—— 如果填的是192.168.1.100或mysql-rds.aliyuncs.com,就 ping 这个地址 - 若 ping 不通,检查 Docker 网络模式:
bridge下容器无法直接访问宿主机127.0.0.1,应改用宿主机真实 IP 或host.docker.internal(Docker Desktop)/ 宿主机网卡 IP(Linux) - 用
telnet <mysql-host> 3306或nc -zv <mysql-host> 3306测试端口是否开放;失败说明防火墙、安全组或 MySQL bind-address 拦住了
Hyperf 的 MySQL 配置要匹配容器网络上下文
env 文件里的 DB_HOST 必须是容器能解析且路由可达的地址,不是开发机视角的“本地”。配置错会导致连接池反复重试、超时后报 Connection refused 或 Operation timed out。
-
DB_HOST填写规则:
– 同 Docker Compose 网络:用服务名,如mysql(对应services.mysql)
– 跨主机或云 RDS:填内网地址(如rm-xxx.mysql.rds.aliyuncs.com),**不能填公网地址 + NAT**(Swoole 协程 hook 对某些 SNAT 场景兼容性差)
– 宿主机数据库(Linux):填宿主机真实局域网 IP,如192.168.1.5,而非127.0.0.1 -
DB_PORT必须是 MySQL 实际监听的端口,注意云数据库可能默认关闭 3306 公网,只开内网端口 - 若使用自签名 SSL 或跳过验证,需在
databases.php的连接配置中显式加:'options' => [PDO::MYSQL_ATTR_SSL_MODE => PDO::SSL_NONE]
协程连接池参数在容器里要更保守
容器资源受限,max_connections 设太高不仅浪费,还容易触发 MySQL 的 Too many connections。容器启动快、扩缩频繁,冷启动连接延迟比物理机更敏感。
-
min_connections建议设为2而非1:避免首个请求因建连阻塞,尤其在高密度部署场景 -
max_connections别照搬文档默认值10或盲目设100;按实际 Worker 数 × 平均并发 × 1.2 算,例如 4 Worker × 30 并发 ≈ 144 → 取整设160,再核对 MySQL 实例的max_connections值(如 RDS 基础版常为 200) -
wait_timeout建议从默认3.0改为1.5:容器内调度更快,协程排队等待太久说明连接池已瓶颈,该扩容或查慢查询了 - 务必在容器启动后运行
php bin/hyperf.php hyperf:pool-status,观察used是否持续接近max_connections,wait是否 > 0
最容易被忽略的是:容器重启后 DNS 缓存可能未刷新,导致服务名解析失败;若用 CoreDNS 或自建 DNS,需确认 ndots 和搜索域配置不干扰短域名解析。这个问题不会报错,只会静默超时。



















