必须用-e mysql_root_password=xxx设置,该变量仅首次初始化生效;若数据卷非空或同时设mysql_allow_empty_password=yes则被忽略;密码需满足8位以上含大小写字母、数字及特殊字符。

docker run 时必须用 MYSQL_ROOT_PASSWORD 环境变量
MySQL 官方镜像(mysql:8.0)不读取配置文件里的密码设置,也不接受 my.cnf 中的 password 字段。唯一可靠、且仅在首次初始化时生效的方式,就是通过 -e MYSQL_ROOT_PASSWORD=xxx 传入。
常见错误现象:
• 启动后仍提示“Access denied for user 'root'@'localhost'”
• 日志里出现 “A temporary password is generated for root@localhost”,说明环境变量根本没生效
• 容器反复重启后密码还是空或临时密码 —— 很可能是因为挂载了已有数据卷(/var/lib/mysql 非空),导致初始化跳过
-
MYSQL_ROOT_PASSWORD必须带值,写成-e MYSQL_ROOT_PASSWORD(无等号右侧)会被忽略 - 若同时设置了
MYSQL_ALLOW_EMPTY_PASSWORD=yes,MYSQL_ROOT_PASSWORD会被静默丢弃 - 密码需满足 MySQL 8.0 默认策略:至少 8 位,含大小写字母+数字+特殊字符(如
MyPass123!)
想创建其他用户或改默认行为?用 /docker-entrypoint-initdb.d/ 挂载 SQL 脚本
环境变量只能设 root 密码,没法控制密码过期、认证插件、host 绑定范围等。这时候就得靠初始化脚本——它只在 /var/lib/mysql 为空时执行一次。
例如,要让 root 可从任意主机登录、并强制使用 mysql_native_password(避免 Navicat 等工具连不上),准备一个 init.sql:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MyPass123!'; ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'MyPass123!'; FLUSH PRIVILEGES;
- 脚本必须放在宿主机路径下,再通过
-v /path/to/init.sql:/docker-entrypoint-initdb.d/init.sql挂载 - 不能用
SET PASSWORD(MySQL 8.0+ 已废弃),必须用ALTER USER ... IDENTIFIED WITH ... BY - 如果脚本执行失败(比如语法错),容器会退出,日志末尾会显示具体报错行
已运行的容器怎么改 root 密码?别碰 skip-grant-tables
对正在运行、但没设密码或想换密码的容器,最安全的做法是进容器执行 SQL,而不是改配置或删数据卷。
操作前提是:容器启动时没加 skip-grant-tables,也没设 MYSQL_ALLOW_EMPTY_PASSWORD=yes;否则会绕过权限系统,带来风险。
- 先用
docker exec -it <container> mysql -uroot -p</container>连上(若当前无密码,直接回车) - 执行时必须指定认证插件,尤其 MySQL 8.0+ 默认是
caching_sha2_password,旧客户端可能不兼容:ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'NewPass456!'; - 改完必须执行
FLUSH PRIVILEGES;,否则新密码不生效 - 注意
'root'@'localhost'和'root'@'%'是两个独立账号,需分别修改
密码连不上?大概率是认证插件或 host 匹配问题
即使密码正确,也常遇到 “Client does not support authentication protocol requested by server” 或 “Access denied for user 'root'@'172.17.0.1'” —— 这不是密码错了,而是连接来源和账号定义不匹配。
- 检查账号 host:用
SELECT user,host FROM mysql.user WHERE user='root';,确认是否有'root'@'%'或'root'@'172.17.0.1' - Navicat / DBeaver 等工具默认用
caching_sha2_password,若服务端插件是mysql_native_password,需在连接属性里勾选“允许不安全认证”或降级驱动 - 本地用
mysql -h 127.0.0.1 -uroot -p和mysql -h localhost -uroot -p行为不同:前者走 TCP,后者走 socket,对应 host 分别是'%'和'localhost'
真正麻烦的从来不是设密码,而是搞清你连的是哪个 root、用的哪种认证、走的是哪条网络路径。每次连不上,先查 user 表,再看客户端日志里报的具体 host 和 plugin 名。











