前言
最近在阿里云服务器上部署项目时,遇到了一个“看似简单却折腾半天”的 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
希望这篇文章能帮到你。如果还有疑问,欢迎在评论区交流!
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2402_87868480/article/details/164142340



