根本原因是连接请求未抵达MySQL进程,常见于Mac上Docker Desktop的端口绑定错误(如127.0.0.1:3306而非0.0.0.0:3306)、MySQL用户host不匹配(需'root'@'%')及认证插件不兼容(需mysql_native_password),或Docker Desktop转发链路异常。
Navicat 连不上 Docker MySQL 的根本原因不是“连不上”,而是连接请求根本没抵达 MySQL 进程
mac 上 navicat 显示“2003 - can't connect to mysql server”或“client does not support authentication protocol”时,90% 的情况不是 navicat 配错了,而是连接请求在抵达容器前就被拦截、转发失败或被拒绝。mysql 容器本身可能压根没收到 tcp 握手包。
常见错误现象包括:
- Navicat 报错
2003,但docker ps显示容器状态是Up - 本地终端执行
telnet localhost 3306或nc -zv localhost 3306直接超时或拒绝连接 - 容器内
mysql -u root -p能正常登录,说明服务本身没问题
检查 -p 端口映射是否生效且绑定到 0.0.0.0
Docker 默认用 -p 3306:3306 启动时,实际监听的是 127.0.0.1:3306(仅限本机回环),而 macOS 的 Docker Desktop 在 M1/M2 上默认使用虚拟机(docker-desktop VM),宿主机的 localhost 指向的是该 VM 的网络空间,不是容器网络。
验证方式(在 Mac 终端运行):
- 执行
docker port <容器名或ID>,确认输出是3306/tcp -> 0.0.0.0:3306,而不是127.0.0.1:3306 - 如果看到
127.0.0.1:3306,说明端口只绑定了回环地址,外部(包括 Navicat)无法访问 - 修复方法:重启容器,显式指定绑定地址:
docker run -p 0.0.0.0:3306:3306 ...
MySQL 用户权限和认证插件必须同时满足两个条件
MySQL 8+ 默认创建的 'root'@'localhost' 只允许容器内部通过 Unix socket 或 127.0.0.1 访问;Navicat 从 Mac 发起的连接走的是 TCP,目标 host 是容器 IP 或宿主机 IP,所以必须存在 'root'@'%' 或 'root'@'172.17.0.%' 这类通配 host 的用户,且认证插件得是 Navicat 支持的。
典型问题组合:
-
SELECT User, Host, plugin FROM mysql.user WHERE User='root';返回root | localhost | caching_sha2_password—— 不满足远程连接要求 - 即使加了
'root'@'%',但 plugin 是caching_sha2_password,而 Navicat 11/12(尤其未更新驱动时)只认mysql_native_password - 解决命令(进容器后执行):
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;
Docker Desktop for Mac 的网络桥接层容易被忽略
M1/M2 Mac 使用的是轻量级 Linux VM(docker-desktop),容器运行在这个 VM 里。宿主机(macOS)和容器之间隔着一层 NAT 和端口转发。这意味着:
Navicat 实际连接的是 macOS 的 localhost:3306,这个请求先被 Docker Desktop 拦截,再转发给 VM 内的容器。任何一环中断都会导致 2003。
- 检查 Docker Desktop 是否正在运行(菜单栏图标亮起)
- 重启 Docker Desktop(不是仅 restart container)常能修复转发链路卡死
- 避免使用
host.docker.internal作为 Navicat 的主机名——它指向 VM 的网关,不是容器 IP;应始终填localhost或宿主机真实 IP(如192.168.x.x) - 若用
docker-compose,确保ports:下写的是"3306:3306",而非"127.0.0.1:3306:3306"
复杂点在于:你改对了 MySQL 用户、插件、密码,也确认了 docker port 输出是 0.0.0.0,但 Navicat 仍连不上——这时候大概率是 Docker Desktop 的转发模块没响应,而不是数据库配置问题。重装或重启它,比反复调 MySQL 权限更有效。


















