能从外部访问Docker中的MySQL,关键在于端口映射、用户权限、bind-address、防火墙/安全组四点全部对齐:必须用-p映射3306端口,创建'root'@'%'用户并授权,将bind-address设为0.0.0.0,同时开放宿主机防火墙及云安全组3306端口。

能从外部访问 Docker 中的 MySQL,关键不在“能不能”,而在于四个点是否全部对齐:端口映射、用户权限、bind-address、防火墙/安全组。漏掉任意一个,连接都会失败,且错误提示往往模糊(比如 Connection refused 或 Access denied for user),容易误判。
docker run 时必须加 -p 映射 3306 端口
容器默认与宿主机网络隔离,不显式映射端口,外部根本无法触达。仅靠改 MySQL 配置没用。
-
docker run -d --name mysql-8 -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:8.0是最简可行命令 - 如果宿主机 3306 已被占用,可换端口(如
-p 3307:3306),但连接时必须用宿主机的3307,不是容器内的3306 - 不要用
--network host想“绕过映射”——它会让容器共享宿主机网络栈,反而可能因 MySQL 绑定逻辑冲突导致启动失败
MySQL 用户必须允许 @'%' 或具体 IP
MySQL 8.0 默认创建的 root 用户只带 'root'@'localhost',即使你连的是宿主机 IP,也属于远程连接,会被拒绝。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 进入容器执行:
docker exec -it mysql-8 mysql -u root -p - 运行授权语句(注意插件兼容性):
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; - 如果执行报错
ERROR 1396 (HY000): Operation ALTER USER failed...,说明'root'@'%'还不存在,先用CREATE USER创建,再GRANT - 生产环境严禁用
%,应限定为具体 IP 段,例如'app-server'@'192.168.10.0/24'
bind-address 必须设为 0.0.0.0
很多 MySQL 官方镜像(尤其是 8.0+)默认 bind-address = 127.0.0.1,这会强制 MySQL 只监听本地回环,无视 @'%' 权限设置。
- 最稳妥方式是启动时通过
--command覆盖:docker run ... --command='--bind-address=0.0.0.0' mysql:8.0 - 或挂载自定义配置文件(如
my.cnf),内容为:[mysqld]\nbind-address = 0.0.0.0
- 不要试图在容器内修改
/etc/mysql/mysql.conf.d/mysqld.cnf后 reload —— 多数官方镜像未启用 systemd,service mysql reload无效,必须重启容器
宿主机防火墙和云安全组常被忽略
即使容器内一切正确,宿主机防火墙或云厂商安全组若未放行对应端口,外部请求会在抵达 MySQL 前就被丢弃,现象是超时或直接拒绝。
- Linux 上检查:
sudo ufw status(Ubuntu)或sudo firewall-cmd --list-ports(CentOS/RHEL) - 开放端口示例:
sudo ufw allow 3306或sudo firewall-cmd --add-port=3306/tcp --permanent && sudo firewall-cmd --reload - 阿里云/腾讯云/AWS 等平台,必须在「安全组」规则中添加入方向 TCP 3306(源 IP 建议限制,不要填
0.0.0.0/0) - 虚拟机场景(如 VMware/VirtualBox)还需确认网络模式为桥接(Bridged),NAT 模式下宿主机 IP 对外部不可见
真正卡住人的地方,往往不是某一步做错了,而是四步里有一步没生效却误以为已成功——比如改了用户权限但没改 bind-address,或者开了防火墙却忘了云安全组。建议每改一项,就用 telnet 宿主机IP 端口 测试端口可达性,再用 MySQL 客户端测试登录,分层验证更省时间。

















