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

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

相关推荐
夏炳辉.21 分钟前
零基础Linux PostgreSQL(psql)从安装到集群高可用全套学习大纲
linux·学习·postgresql
Horn Still Sounds33 分钟前
【Linux 系统编程】IPC 进程间通信全解:管道、有名管道与信号
linux·运维·服务器
xiaoye-duck42 分钟前
《Linux 网络编程》应用层自定义协议(一):序列化、sk_buff 与粘包半包处理
linux·网络
莫陌尛.44 分钟前
StarRocks Iceberg MinIO S3 301报错完整修复文档(Docker环境)
java·docker·容器
郭老师-嵌入式1 小时前
arm linux 移植 udhcp 与 使用
linux·服务器·arm开发
代码终究输给规则1 小时前
MATLAB r2026a 安装包和安装教程
linux·运维·服务器
临岸草惊风.1 小时前
简单VASP计算INCAR设置(结构优化OPT、静态自洽SCF、能带BAND、态密度DOS)
linux·dft
钟良堂1 小时前
Ubuntu 20.04 部署 ORB_SLAM3 完整流程与踩坑总结
linux·运维·ubuntu
拾光Ծ1 小时前
【MySQL】基础入门:库操库、数据表操作与数据类型详解
数据库·sql·mysql·数据类型·库操作·表操作