Node.js Docker容器无法连接宿主机MySQL报错ECONNREFUSED问题咨询
结论先行
该问题和node:12-alpine镜像的mysql客户端无任何关联,是两项配置缺失导致的。
问题根因解释
1. 连接172.17.0.1被拒绝的核心原因
Ubuntu默认安装的MySQL 8.0,默认配置仅监听本地回环地址127.0.0.1的3306端口,不会监听Docker网桥对应的网关地址172.17.0.1的请求,因此无论是容器内访问172.17.0.1:3306,还是宿主机本身主动访问172.17.0.1:3306,都会触发连接拒绝的报错。
2. 宿主机加hosts映射后连接成功的原因
Node使用的mysql驱动存在默认逻辑:当配置的host地址被解析为本地地址时,会优先走Unix Socket连接MySQL,而非走TCP链路,因此你在宿主机/etc/hosts添加172.17.0.1 host.docker.internal配置后,宿主机运行的代码实际没有走TCP请求172.17.0.1,直接通过本地Socket完成了连接,才会出现连接成功的现象。
3. 容器内配置host.docker.internal却请求127.0.0.1的原因
排除代码配置覆盖的情况外,本质是容器内的mysql驱动尝试连接172.17.0.1:3306被拒绝后,错误回显将目标地址误显示为127.0.0.1,属于回显信息误导,并非真的解析到了127.0.0.1。
修复步骤
按顺序执行以下配置即可解决:
- 修改宿主机MySQL监听配置
编辑MySQL配置文件(默认路径为/etc/mysql/mysql.conf.d/mysqld.cnf),找到bind-address参数,将默认值127.0.0.1修改为:
若需要允许所有Docker容器网段访问,可临时改为bind-address = 127.0.0.1,172.17.0.10.0.0.0(生产环境不推荐),修改完成后重启MySQL服务:systemctl restart mysql - 配置MySQL账号访问权限
你用于连接的数据库账号需要开放Docker网段的访问权限,执行SQL授权语句:GRANT ALL PRIVILEGES ON 你的业务库名.* TO '你的连接账号'@'172.17.%' IDENTIFIED BY '你的账号密码'; FLUSH PRIVILEGES; - 保留原有容器启动参数
不需要修改你之前添加的--add-host=host.docker.internal:host-gateway启动参数,代码中host配置保持host.docker.internal即可。
验证方法
配置完成后先在宿主机执行telnet 172.17.0.1 3306确认端口可连通,再进入容器执行同样的telnet命令验证链路正常,最后运行Node代码测试连接即可。
内容的提问来源于stack exchange,提问作者Drake Orfeo
相关产品推荐
相关产品推荐

