最近在阿里云服务器上部署项目时,遇到了一个“看似简单却折腾半天”的 mysql 连接问题:
从本地 navicat 连不上云服务器上的 mysql(docker 容器),报错 1045 access denied,甚至连服务器上用 mysql -u root -p 也登录失败。
本文将完整记录从问题出现到彻底解决的每一步,包括密码重置、安全组配置、用户权限、认证插件等常见坑点,希望给遇到类似问题的朋友一些参考。
一、问题现象
1. 本地命令行登录报错
[root@iz0jlid3me315igdq5f88pz ~]# mysql error 1045 (28000): access denied for user 'root'@'localhost' (using password: no)
即使加上 -p 输入密码,也提示 access denied,说明 root 密码遗忘或丢失。
2. navicat 远程连接失败
连接信息:
- 主机:公网 ip xxxxxxxx
- 端口:
3307(docker 映射的端口) - 用户名:
root - 报错:
1045 - access denied for user 'root'@'117.69.22.210' (using password: yes)
这个错误表明网络是通的(否则会超时或拒绝),但认证失败。
二、环境说明
- 云服务器:阿里云 ecs(centos 7)
- mysql 部署方式:docker 容器(镜像
mysql:8.0.29) - 容器名:
share_mysql - 端口映射:宿主机
3307-> 容器内3306 - 本地客户端:windows 10 + navicat 16
三、排查过程与解决步骤
第一步:检查网络连通性
1. 确认 mysql 服务监听状态
在服务器上执行:
netstat -tlnp | grep 3307
输出:
tcp 0 0 0.0.0.0:3307 0.0.0.0:* listen 2345/docker-proxy
说明 docker 已正确映射端口。
2. 测试端口是否可达
在本地 windows powershell 中:
test-netconnection 服务器公网ip -port 3307
若显示 tcptestsucceeded : true 表示网络已通。
若为 false,则需要检查阿里云安全组和服务器防火墙。
3. 开放阿里云安全组(入方向)
- 登录阿里云控制台 → ecs → 安全组 → 配置规则 → 入方向
- 添加规则:端口
3307/3307,授权对象0.0.0.0/0(测试后应改为自己本地公网 ip) - 若使用轻量应用服务器,还需在“防火墙”页面放行端口。
4. 检查服务器内部防火墙(若使用 firewalld)
sudo firewall-cmd --add-port=3307/tcp --permanent sudo firewall-cmd --reload
经过以上步骤,test-netconnection 返回 true,网络问题排除。
第二步:检查 mysql 用户权限
进入容器查看用户表:
docker exec -it share_mysql mysql -u root -p
但此时依然提示密码错误,说明我们不知道 root 密码,需要重置。
第三步:重置 docker 容器内的 mysql root 密码
由于容器内数据需要保留,不能简单删除容器重建。采用 挂载数据卷 + --skip-grant-tables 方式重置。
1. 查看数据卷挂载情况
docker inspect share_mysql | grep -a 5 "mounts"
找到 source 路径,例如 /var/lib/docker/volumes/xxx/_data。
2. 停止原容器
docker stop share_mysql
3. 启动临时容器,挂载相同数据卷,并跳过权限表
docker run -d --name mysql_reset \ -v /var/lib/docker/volumes/xxx/_data:/var/lib/mysql \ -e mysql_allow_empty_password=yes \ mysql:8.0.29 \ --skip-grant-tables
(若没有使用卷,可使用 --volumes-from share_mysql)
4. 进入临时容器,无密码登录 mysql
docker exec -it mysql_reset mysql -u root
进入后执行:
flush privileges; alter user 'root'@'%' identified by 'yournewstrongpwd123!'; alter user 'root'@'localhost' identified by 'yournewstrongpwd123!'; flush privileges; exit;
注意:密码要符合 mysql 8.0 的强度要求(大小写+数字+特殊字符,8位以上)。
5. 清理临时容器,重启原容器
docker stop mysql_reset docker rm mysql_reset docker start share_mysql
6. 验证新密码
docker exec -it share_mysql mysql -u root -p
输入新密码,成功进入则重置完成。
第四步:解决 navicat 连接时的认证插件问题(可选)
如果重置后 navicat 仍报 1045,可能是 mysql 8.0 默认的 caching_sha2_password 与老版本 navicat 不兼容。
可以将认证插件改为 mysql_native_password:
在 mysql 中执行:
alter user 'root'@'%' identified with mysql_native_password by 'yournewstrongpwd123!'; alter user 'root'@'localhost' identified with mysql_native_password by 'yournewstrongpwd123!'; flush privileges;
第五步:navicat 连接参数最终确认
- 主机:xxxxxxxx(公网 ip)
- 端口:
3307(映射端口,不是 3306) - 用户名:
root - 密码:刚重置的密码
- ssl 设置:关闭(测试阶段)
点击“测试连接”,成功!
四、问题总结
根本原因
- 密码遗忘:容器 mysql 的 root 密码未知,导致本地和远程都无法认证。
- 端口未开放:阿里云安全组未放行映射的
3307端口,初次尝试时连接超时。 - (可选)认证插件不兼容:老版本 navicat 可能不支持
caching_sha2_password。
经验教训
- 部署 mysql 后务必记录并妥善保管 root 密码。
- 使用 docker 映射端口时,安全组要开放映射后的宿主机端口,而不是容器内端口。
- mysql 8.0 的认证方式与 5.7 不同,若客户端较旧,需主动改为
mysql_native_password。 skip-grant-tables是重置密码的有效手段,但注意操作后要刷新权限并移除该选项。
预防建议
- 考虑使用
docker-compose并设置mysql_root_password环境变量,避免密码丢失。 - 为安全考虑,远程访问应限制授权 ip,而非直接使用
%。 - 定期备份数据卷,防止误操作导致数据丢失。
五、参考命令合集
# 查看端口监听 netstat -tlnp | grep 3307 # 测试端口连通性(windows powershell) test-netconnection 你的公网ip -port 3307 # 查看容器数据卷 docker inspect share_mysql | grep -a 5 "mounts" # 重置密码(临时容器方式) docker stop share_mysql docker run -d --name mysql_reset -v 数据卷路径:/var/lib/mysql -e mysql_allow_empty_password=yes mysql:8.0.29 --skip-grant-tables docker exec -it mysql_reset mysql -u root # 执行 alter user ... docker stop mysql_reset && docker rm mysql_reset docker start share_mysql
以上就是mysql远程连接故障排查全记录(linux+docker+navicat)的详细内容,更多关于mysql远程连接故障排查的资料请关注代码网其它相关文章!
发表评论