0. 问题背景

在部署 KamaChat 微服务项目时,我通过 Docker 运行了一个包含 MySQL 8.0 的集成镜像。虽然在宿主机(M4 Mac mini)上已经做好了端口映射(3307:3306),且通过 docker exec 进入容器内部可以正常登录数据库,但使用 GoLand 的 Database 工具连接时,始终报错:

Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.


1. 排查过程

第一阶段:用户权限校验

起初我认为是 root 用户默认禁止远程登录的问题。我进入容器执行了常规的权限修改:

1
2
3
USE mysql;
UPDATE user SET host = '%' WHERE user = 'root';
FLUSH PRIVILEGES;

结果: 修改后报错依旧,说明问题不在 MySQL 的用户授权表,而是在更底层的网络监听阶段。

第二阶段:网络监听排查 (关键点)

在 Docker 环境下,MySQL 默认的配置文件往往为了安全,将监听地址绑定在 127.0.0.1

  • 原理: 容器内的 127.0.0.1 仅代表容器自身的回环网卡。宿主机通过映射端口访问时,流量是从容器的虚拟网卡(通常是 eth0)进入的。如果 MySQL 只监听 127.0.0.1,它会直接丢弃来自虚拟网卡的外部请求。

2. 解决方案

通过修改 MySQL 的配置文件,将监听地址由本地改为全接口监听。

第一步:定位配置文件

进入容器终端:

1
docker exec -it gochat-container bash

查找 bind-address 所在位置:

1
grep -r "bind-address" /etc/mysql/

这次位于 /etc/mysql/mysql.conf.d/mysqld.cnf

第二步:修改配置

使用 vim 打开文件,找到如下行:

1
bind-address = 127.0.0.1

修改为:

1
bind-address = 0.0.0.0

第三步:重启服务

1
service mysql restart

3. 最终验证

回到 GoLand 的 Database 配置界面,重新点击 Test Connection

  • Host: 127.0.0.1
  • Port: 3307
  • User: root
  • Password: (根据实际情况填写)

结果: 连接成功,显示 Ping: 10ms


4. 总结

在处理 Docker 数据库连接问题时,应遵循以下排查优先级:

  1. 宿主机端口映射:确保 docker ps 中显示的端口无误。
  2. MySQL 绑定地址:检查 bind-address 是否为 0.0.0.0
  3. 用户授权:确保 user 表中对应账号的 host 字段已改为 %

尤其在 M4 芯片通过模拟层运行 amd64 镜像时,网络响应可能会有延迟,建议适当调大 IDE 的连接超时时间(Timeout)。 通过这次复盘,我加深了对 Docker 网络模型和 MySQL 配置的理解,为今后类似问题的解决提供了宝贵经验。