thinkphp在docker中连不上mysql,90%因hostname配置错误:必须填docker-compose.yml中定义的mysql服务名(如db),不可用localhost或127.0.0.1;同时需确保mysql用户授权允许'%'或对应容器网段、bind-address=0.0.0.0、认证插件设为mysql_native_password,并通过.env动态注入db_host。

ThinkPHP 在 Docker 容器里连不上数据库,90% 是因为 hostname 写成了 localhost 或 127.0.0.1,而不是 MySQL 服务名。
ThinkPHP 的 database.php 里 hostname 必须填容器名
在 docker-compose.yml 中定义的 MySQL 服务名(比如 db、mysql、database),就是 PHP 容器必须使用的地址。不能写 localhost,也不能写宿主机的 127.0.0.1——那会指向 PHP 容器自己,而它没装 MySQL。
-
hostname值必须和docker-compose.yml里 services 下的 MySQL 服务名完全一致(区分大小写) - 如果服务定义为
services: db: image: mysql:8.0,则hostname就是db - TP6 的配置字段是
hostname,不是host;TP5 是hostname或DB_HOST(环境变量方式) - 别用
host.docker.internal:它在 Linux Docker Desktop 和部分旧版上不可靠,且不适用于生产级 Compose 网络
Docker Compose 启动顺序与 MySQL 就绪判断
PHP 容器启动时,MySQL 容器可能刚拉起、还没初始化完数据库或用户权限,直接连接会报 Connection refused 或 Access denied。
-
depends_on只控制启动顺序,不等待 MySQL “就绪”——它只等容器进程起来,不管 mysqld 是否能响应 SQL - 必须加健康检查(healthcheck)并让 PHP 等待:在 MySQL 服务块中定义
healthcheck,例如用mysqladmin ping - PHP 启动脚本里加重试逻辑更可靠,比如:
while ! mysqladmin ping -h db -u root -ppassword --silent; do sleep 2; done - ThinkPHP 自身不提供连接重试机制,得在容器启动入口(如
entrypoint.sh)里处理
MySQL 用户权限必须允许容器网络 IP 连接
报错 Access denied for user 'root'@'172.20.0.3' 不是密码错,是用户授权范围不对。MySQL 默认只允许 root@localhost,而 PHP 容器发起的连接来自 Docker 网络内的动态 IP(如 172.20.0.3)。
- 进 MySQL 容器执行:
CREATE USER 'app'@'%' IDENTIFIED BY 'pass123'; - 再执行:
GRANT ALL ON mydb.* TO 'app'@'%'; FLUSH PRIVILEGES; - 不要删
root@localhost,但新应用账号必须带@'%'(开发环境)或明确指定子网(如@'172.20.0.%') - MySQL 8.0+ 默认用
caching_sha2_password插件,PHP 7.4 以下可能不兼容,需显式设为mysql_native_password
ThinkPHP 多环境配置别混用 .env 和 database.php
很多人把 .env 里的 DB_HOST=db 和 config/database.php 里的 hostname => 'localhost' 同时留着,结果框架优先读 database.php,.env 彻底被忽略。
- 选一种方式:要么全走
.env(推荐),在database.php中用$_ENV['DB_HOST'] ?? 'db'动态取值 - 要么全走
database.php,确保hostname字段值已按容器名更新 - TP6 的
database.php示例写法:'hostname' => $_ENV['DB_HOST'] ?? 'db', 'hostport' => (int)($_ENV['DB_PORT'] ?? 3306) - 注意
hostport必须是整数类型,字符串'3306'会导致静默 fallback 到默认端口
最易被忽略的是:MySQL 容器的 bind-address 默认可能是 127.0.0.1 或 ::1,这会拒绝来自其他容器的 TCP 连接。必须在 MySQL 配置中设为 bind-address = 0.0.0.0,或通过 command 覆盖启动参数。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











