mysql连接失败首要排查服务是否运行:先用docker ps确认容器状态,再exec进入容器执行mysql -u root -p验证;若失败则查docker logs,常见原因包括服务未启动、bind_address限制、用户host不匹配及反向dns超时。

进容器内部验证MySQL服务是否真在运行
很多连接失败其实不是网络问题,而是MySQL根本没起来。别急着改配置,先确认服务状态。
- 用
docker ps | grep mysql看容器是不是Up状态;如果是Exited,直接跳到日志分析 - 执行
docker exec -it <mysql-container> /bin/bash</mysql-container>进入容器;失败就说明容器生命周期异常,不是连接问题 - 在容器里跑
mysql -u root -p(密码是启动时设的MYSQL_ROOT_PASSWORD);连不上就查docker logs <mysql-container></mysql-container>,常见报错如Can't create/write to file '/var/run/mysqld/mysqld.pid'是权限或数据卷挂载问题
检查MySQL是否监听外部TCP连接
默认情况下,MySQL只监听 127.0.0.1:3306,容器外发来的连接会被拒绝——即使端口映射了也没用。
- 进容器后执行
netstat -tlnp | grep :3306或ss -tlnp | grep :3306;如果只看到127.0.0.1:3306,说明没对外监听 - 根本解法是在启动容器时加配置:通过
-e MYSQL_ROOT_PASSWORD=xxx启动后,MySQL 8+ 默认已禁用bind-address限制;但若自定义了my.cnf,务必确认里面没有bind-address = 127.0.0.1或等效配置 - 临时验证可手动改:编辑
/etc/mysql/mysql.conf.d/mysqld.cnf,注释掉bind-address行,然后service mysql restart(注意:Docker 容器内不推荐长期这样操作)
验证用户权限是否匹配真实来源IP
错误信息里出现 user01@'172.17.0.1' 或 user01@'10.10.10.10' 就是典型征兆:你建的是 user01@'localhost',但宿主机或另一容器连过来时,来源不是 localhost,而是 Docker 网络分配的真实 IP。
- 进 MySQL 执行
SELECT User, Host FROM mysql.user;,确认目标用户对应的Host字段值是否覆盖你的连接来源(比如%、172.17.%或具体宿主机网关 IP) - 创建兼容用户:运行
CREATE USER 'user01'@'%' IDENTIFIED BY 'password123'; GRANT ALL ON mydb.* TO 'user01'@'%'; FLUSH PRIVILEGES;;生产环境慎用%,优先指定子网段 - 注意:
localhost在 MySQL 中是特殊语义,强制走 socket,不接受任何 TCP 连接;127.0.0.1才走 TCP,但仅限本机回环,对 Docker 容器无效
排查反向DNS解析导致的超时卡顿
输入密码后卡 5–10 秒才进 MySQL?大概率是 MySQL 在做反向 DNS 查询,而 Docker 内网 IP(如 172.18.0.3)没有 PTR 记录,只能等超时。
- 进 MySQL 执行
SHOW VARIABLES LIKE 'skip_name_resolve';;如果值是OFF,说明开启了解析 - 修复方式:启动容器时加参数
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --skip-name-resolve;或者挂载自定义my.cnf,在[mysqld]下写skip-name-resolve - 这个选项必须在 MySQL 启动前设置;运行中无法动态开启,
SET GLOBAL不生效
实际调试时最容易被忽略的,是把“容器能连上”和“外部能连上”混为一谈——前者只验证服务进程,后者还强依赖网络路径、权限模型、DNS 行为三重叠加。每层都得单独切进去看,不能靠猜。











