MySQL 远程连接故障排查全记录(Linux + Docker + Navicat)

前言

最近在阿里云服务器上部署项目时,遇到了一个"看似简单却折腾半天"的 MySQL 连接问题:

从本地 Navicat 连不上云服务器上的 MySQL(Docker 容器),报错 1045 Access denied,甚至连服务器上用 mysql -u root -p 也登录失败。

本文将完整记录从问题出现到彻底解决的每一步,包括密码重置、安全组配置、用户权限、认证插件等常见坑点,希望给遇到类似问题的朋友一些参考。


一、问题现象

1. 本地命令行登录报错

bash 复制代码
[root@iZ0jlid3me315igdq5f88pZ ~]# mysql
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

即使加上 -p 输入密码,也提示 Access denied,说明 root 密码遗忘或丢失。

连接信息:

  • 主机:公网 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 服务监听状态

在服务器上执行:

bash 复制代码
netstat -tlnp | grep 3307

输出:

bash 复制代码
tcp        0      0 0.0.0.0:3307            0.0.0.0:*               LISTEN      2345/docker-proxy

说明 Docker 已正确映射端口。

2. 测试端口是否可达

在本地 Windows PowerShell 中:

bash 复制代码
Test-NetConnection 服务器公网IP -Port 3307

若显示 TcpTestSucceeded : True 表示网络已通。

若为 False,则需要检查阿里云安全组和服务器防火墙。

3. 开放阿里云安全组(入方向)
  • 登录阿里云控制台 → ECS → 安全组 → 配置规则 → 入方向

  • 添加规则:端口 3307/3307,授权对象 0.0.0.0/0(测试后应改为自己本地公网 IP)

  • 若使用轻量应用服务器,还需在"防火墙"页面放行端口。

4. 检查服务器内部防火墙(若使用 firewalld)
bash 复制代码
sudo firewall-cmd --add-port=3307/tcp --permanent
sudo firewall-cmd --reload

经过以上步骤,Test-NetConnection 返回 True,网络问题排除。


第二步:检查 MySQL 用户权限

进入容器查看用户表:

bash 复制代码
docker exec -it share_mysql mysql -u root -p

但此时依然提示密码错误,说明我们不知道 root 密码,需要重置。


第三步:重置 Docker 容器内的 MySQL root 密码

由于容器内数据需要保留,不能简单删除容器重建。采用 挂载数据卷 + --skip-grant-tables 方式重置。

1. 查看数据卷挂载情况
bash 复制代码
docker inspect share_mysql | grep -A 5 "Mounts"

找到 Source 路径,例如 /var/lib/docker/volumes/xxx/_data。

2. 停止原容器
bash 复制代码
docker stop share_mysql
3. 启动临时容器,挂载相同数据卷,并跳过权限表
bash 复制代码
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
bash 复制代码
docker exec -it mysql_reset mysql -u root

进入后执行:

sql 复制代码
FLUSH PRIVILEGES;
ALTER USER 'root'@'%' IDENTIFIED BY 'YourNewStrongPwd123!';
ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewStrongPwd123!';
FLUSH PRIVILEGES;
EXIT;

注意:密码要符合 MySQL 8.0 的强度要求(大小写+数字+特殊字符,8位以上)。

5. 清理临时容器,重启原容器
sql 复制代码
docker stop mysql_reset
docker rm mysql_reset
docker start share_mysql
6. 验证新密码
sql 复制代码
docker exec -it share_mysql mysql -u root -p

输入新密码,成功进入则重置完成。


如果重置后 Navicat 仍报 1045,可能是 MySQL 8.0 默认的 caching_sha2_password 与老版本 Navicat 不兼容。

可以将认证插件改为 mysql_native_password:

在 MySQL 中执行:

sql 复制代码
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 设置:关闭(测试阶段)

点击"测试连接",成功!


四、问题总结

根本原因

  1. 密码遗忘:容器 MySQL 的 root 密码未知,导致本地和远程都无法认证。

  2. 端口未开放 :阿里云安全组未放行映射的 3307 端口,初次尝试时连接超时。

  3. (可选)认证插件不兼容 :老版本 Navicat 可能不支持 caching_sha2_password。

经验教训

  • 部署 MySQL 后务必记录并妥善保管 root 密码。

  • 使用 Docker 映射端口时,安全组要开放映射后的宿主机端口,而不是容器内端口。

  • MySQL 8.0 的认证方式与 5.7 不同,若客户端较旧,需主动改为 mysql_native_password。

  • skip-grant-tables 是重置密码的有效手段,但注意操作后要刷新权限并移除该选项。

预防建议

  • 考虑使用 docker-compose 并设置 MYSQL_ROOT_PASSWORD 环境变量,避免密码丢失。

  • 为安全考虑,远程访问应限制授权 IP ,而非直接使用 %。

  • 定期备份数据卷,防止误操作导致数据丢失。


五、参考命令合集

sql 复制代码
# 查看端口监听
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

希望这篇文章能帮到你。如果还有疑问,欢迎在评论区交流!

相关推荐
欧米欧18 分钟前
Linux系统篇(七),环境变量的底层溯源,核心获取机制与安全应用
linux·运维·服务器
Ruiery28 分钟前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全
todoitbo1 小时前
群晖NAS部署JmalCloud:Docker安装、文件管理、博客与公网访问完整教程
运维·docker·容器
时间售卖铺1 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw1 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
逆风的蚂蚁3 小时前
linux服务器性能调整怎么落地?我把 CPU 调度、I/O 优先级和内核参数这几个旋钮都拧了一遍
linux·运维·服务器
数据库小组4 小时前
NineData 实战教程:MySQL 5.5 数据迁移同步到 MySQL 8.0(跨版本升级)
数据库·mysql·mysql优化·数据库开发·数据库迁移·版本升级·数据复制
cnskylee6 小时前
【MySQL】麒麟V10 SP3系统安装MySQL-Commercial-8.0.46
数据库·mysql·adb
梦幻通灵6 小时前
修改MySQL数据库递增序列【持续更新】
数据库·mysql
沫璃染墨7 小时前
从零入门计算机网络系列(十一):HTTP协议进阶——从重定向原理到GET/POST与Fiddler抓包
linux·服务器·开发语言·网络·c++·tcp/ip·html