连不上mysql容器需检查:-p端口映射是否显式指定、--network自定义网络下必须用-p而非直连ip;linux需确认防火墙未拦截3306;root密码须通过mysq_root_password设置且仅首次初始化生效;init脚本仅在空数据目录时执行;8.0默认认证插件不兼容旧客户端,需加--default-authentication-plugin=mysql_native_password。

docker run 启动 MySQL 容器时连不上?检查 -p 和 --network
默认情况下 docker run -d -p 3306:3306 mysql:8.0 看似正确,但宿主机 3306 被占用、或容器没暴露端口、或用了自定义网络却没配好网关,都会导致本地 mysql -h 127.0.0.1 -P 3306 连不上。
-
-p 3306:3306必须显式写,MySQL 镜像不自动发布端口 - 若用
--network mynet,宿主机无法直连容器 IP,得走-p映射,或改用docker exec -it mysql-container mysql -uroot -p - Mac/Windows 上 Docker Desktop 的
localhost可连,Linux 宿主机需确认 iptables/firewalld 没拦截 3306
root 密码设了却还是提示 Access denied?看 MYSQ_ROOT_PASSWORD 和初始化时机
MySQL 官方镜像要求必须通过环境变量 MYSQ_ROOT_PASSWORD 设置 root 密码,且只在容器首次启动、数据目录为空时生效。如果反复删容器重跑但没清 -v 挂载的卷,旧数据还在,密码不会被覆盖。
- 务必加
-e MYSQL_ROOT_PASSWORD=abc123,不设则容器启动失败(8.0+) - 挂载了
-v ./mysql-data:/var/lib/mysql就得自己清目录,否则再跑也不会重新初始化 - 想跳过密码直接进,可临时加
--skip-grant-tables,但仅限调试,不能用于生产
容器里执行 SQL 初始化脚本失败?注意 /docker-entrypoint-initdb.d/ 的触发条件
把 init.sql 放进 /docker-entrypoint-initdb.d/ 目录下,只有在容器首次初始化数据库时才执行——也就是 /var/lib/mysql 为空、且 MYSQL_ROOT_PASSWORD 已设置的前提下。
- SQL 文件必须是
.sql、.sql.gz或.sh后缀,且权限为 644(非 root 用户也能读) - 文件内不要写
USE database_name,因为此时默认库还没建;应显式写CREATE DATABASE IF NOT EXISTS mydb;再CREATE TABLE mydb.users... - 如果挂载了已有数据卷,这个目录下的脚本完全不会运行,静默跳过
MySQL 8.0 默认认证插件不兼容老客户端?改 default-authentication-plugin
MySQL 8.0 容器默认用 caching_sha2_password,而很多旧版客户端(如某些 Python MySQLdb、Navicat 旧版)只支持 mysql_native_password,连上后执行任何语句都报 Authentication plugin 'caching_sha2_password' cannot be loaded。
- 启动时加
--default-authentication-plugin=mysql_native_password即可降级兼容 - 或者进容器后手动改:先
docker exec -it mysql mysql -uroot -p,再运行ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123'; - 该参数只影响新创建用户的默认插件,已存在的用户需单独
ALTER USER
最常被忽略的是挂载卷和初始化脚本的耦合关系:以为丢个 SQL 文件进去就能每次重跑都生效,其实它只咬第一口。数据目录一旦存在,后续所有初始化逻辑全失效。











