上个月接到一个新项目,需要搭建一套测试环境。技术栈很常规:Spring Boot + MySQL,考虑到环境的统一性和便于管理,我决定用Docker来部署MySQL。
按照以往的经验,搭建Docker MySQL应该很简单:拉镜像、启动容器、配置端口映射,然后就能用了。结果现实给了我一个响亮的耳光。
容器启动后,我用客户端工具连接MySQL,死活连不上。同事们也试了,都是同样的问题。这让我很纳闷,明明按照标准流程操作的,怎么就连不上呢?
当你在Java项目中,或者是用MySQL客户端进行连接的时候会提示这样的问题:

Connection refused 这个错误让人很困惑。我第一反应是网络问题,赶紧让运维同学检查。结果他们说:
但就是外部连不上!这就奇怪了,端口开着,服务正常,防火墙也没问题,为什么还是连不上呢?
遇到这种问题,我习惯先从最基础的开始排查。毕竟做运维这么多年,见过太多"应该没问题"结果确实有问题的案例。
服务器端检查
首先登录到MySQL所在的服务器,检查端口监听情况:

可以看到3351端口确实在监听,进程也正常。防火墙状态也是开启的,规则看起来没问题。
客户端网络测试
然后在我的电脑上用telnet测试网络连通性:

telnet能通,说明网络层面是OK的。
到这里我就有点懵了,网络通、端口开、服务正常,那为什么MySQL客户端就是连不上呢?是不是MySQL本身有什么配置问题?
既然外部网络层面没问题,那就得看看MySQL内部是怎么回事了。我用的是Docker部署,所以先进入容器看看情况。
docker ps
# 找到MySQL容器ID
docker exec -it b3bcda373f8d bash进入容器后,我试着在容器内部连接MySQL:

有意思的是,容器内部直接用mysql -u root -p是能连上的。这就说明MySQL服务本身没问题,问题应该出在权限配置上。
这时候我想起来一个重要的点:Docker的端口映射机制。
从docker ps的结果可以看到,容器的端口映射是0.0.0.0:3351->3306/tcp,也就是说:
那么问题来了,MySQL的用户权限配置是怎样的?是不是只允许本地连接?
既然能在容器内连接MySQL,那我就在MySQL里查查用户权限配置。执行了这个查询:
SELECT user, host FROM mysql.user WHERE user = 'root';
看到这个结果我就明白了!问题出在这里:
root用户只有localhost权限!
你看,查询结果显示root用户的host字段是localhost,这就意味着MySQL的root用户只允许从localhost连接,任何外部IP的连接都会被拒绝。
这就解释了为什么:
问题的本质:这不是网络问题,不是端口问题,而是MySQL用户权限配置问题!
这里有个很重要的概念需要理清楚:
当你通过Docker端口映射访问MySQL时,请求的流向是:
外部客户端 → 宿主机3351端口 → Docker端口映射 → 容器内3306端口 → MySQL服务在这个过程中,MySQL看到的连接来源并不是外部客户端的IP,而是经过Docker网络处理后的IP。但即便如此,root@localhost的权限配置还是太严格了,只允许真正的localhost连接。
找到问题根源后,解决方案就很明确了。我需要给root用户添加远程连接权限。
在容器内连接MySQL后,执行以下SQL:
-- 创建允许任何IP连接的root用户
CREATE USER 'root'@'%' IDENTIFIED BY '1231231';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;这样修改后,再查看用户列表:
SELECT user, host FROM mysql.user WHERE user = 'root';应该能看到两条记录:
root | localhost - 本地连接用root | % - 远程连接用如果从安全角度考虑,不想开放root的远程权限,可以创建专门的应用用户:
-- 创建专门的应用用户
CREATE USER 'test'@'%' IDENTIFIED BY 'test1234';
GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'test'@'%';
FLUSH PRIVILEGES;然后修改应用配置:
spring.datasource.username=test
spring.datasource.password=test1234其实排查到这里,解决方案已经很明确了。但我想试试用一个更现代化的方法来解决这个问题。
最近在用腾讯云Lighthouse AI,这个工具真的很强大。关于它的更多详细信息,大家可以查看这篇文章腾讯云Lighthouse AI真的杀疯了,聊聊天就能运维了!。
我就简单问了一句话:我的mysql是使用docker部署的,但是目前我在外部使用root账号连接不到它

AI立即给出了诊断思路,还挺准确的。接下来,因为我的密码没有配置到环境中,也没有配置到配置文件中,所以直接告诉了它密码,它就帮我直接解决了:

它的关键修复操作是:

本质上就是执行了:
CREATE USER 'root'@'%' IDENTIFIED BY '1231231';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;修改完成后,再次测试外部连接,成功了!
说实话,用AI来辅助运维真的提高了不少效率。特别是这种常见问题,它基本上能秒解决。不过前提是你得把问题描述清楚,并且最好能提供一些上下文信息。
这次踩坑让我明白了一个道理:不要想当然。
我一开始就认为MySQL Docker部署很简单,端口映射配好就行了。完全没想到MySQL还有用户权限这一层限制。
关键的收获:
root@localhost权限真的只能本地连接,哪怕通过Docker端口映射也不行另外,腾讯云Lighthouse AI确实好用,能够快速定位问题并给出解决方案。以前遇到这种问题可能要自己搜半天,现在直接问AI就行了。
这次踩坑主要是两个地方:
用netstat或docker ps看到端口在监听,不代表外部就能连上。MySQL还有自己的权限控制层。
我就是被0.0.0.0:3351->3306/tcp这个端口映射误导了,以为端口映射了就万事大吉。
root@localhost和root@%是两个不同的用户,权限完全独立:
localhost:只能容器内部连接%:可以外部连接(但排除localhost)如果你想外部连接,必须有root@%权限。
我的排查顺序:
这个顺序能快速定位到底是网络问题还是权限问题。
说实话,手动排查虽然能学到东西,但效率确实不如直接问AI。腾讯云Lighthouse AI在这种常见问题上基本是秒解决。
以后遇到类似问题,我可能会先问AI,然后再手动验证一下解决方案。
总之,Docker部署MySQL看似简单,实际上坑还挺多的。记录下来,希望其他人别再踩同样的坑。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。