必须先停旧容器并完整备份数据,因MySQL 5.7与8.0数据字典不兼容,直接挂载旧数据启动会失败;需用mysqldump导出全量数据及配置,通过临时容器执行mysql_upgrade升级系统表,并修改my.cnf兼容参数及root用户认证插件。

必须先停旧容器并完整备份数据
不备份就升级等于裸奔。Docker里看似只是换镜像,但MySQL 5.7和8.0的数据字典(DD)结构不兼容,直接挂载旧数据目录启动8.0容器会卡在 Failed to initialize DD tables,连日志都刷不出有效错误。
实操建议:
- 用
docker exec -i mysql57 mysqldump -u root -p'xxx' --all-databases --single-transaction --routines --events > backup.sql导出全量(含系统库mysql,否则用户权限丢失) - 同步导出配置:确认旧容器挂载的
my.cnf路径,docker cp mysql57:/etc/mysql/my.cnf ./my.cnf.bak - 记下 volume 名或宿主机路径:
docker inspect mysql57 | grep -A 5 Mounts,避免重建时误删/var/lib/mysql挂载点
拉取新镜像后不能直接启动,得走 mysql_upgrade 流程
官方镜像不会自动执行 mysql_upgrade —— 它不是初始化脚本的一部分,也不是容器启动时的默认行为。跳过这步,mysql.user 表字段缺失、系统视图失效、存储过程报错都是常态。
实操建议:
- 启动临时容器,只挂数据卷 + 配置,不启动 MySQL:
docker run -d --name mysql8-upgrade -v mysql-data:/var/lib/mysql -v $(pwd)/my.cnf:/etc/mysql/my.cnf:ro mysql:8.0 tail -f /dev/null - 进容器手动跑升级:
docker exec mysql8-upgrade mysql_upgrade -u root -p'xxx'(密码必须和旧实例一致) - 升级成功后,
docker stop mysql8-upgrade && docker rm mysql8-upgrade,再启正式容器
my.cnf 和认证插件是两个高频崩点
5.7 的配置文件照搬进8.0容器,大概率启动失败。MySQL 8.0 启动时会严格校验参数合法性,NO_AUTO_CREATE_USER 这种已移除的 sql_mode 值会导致服务立即退出;而 caching_sha2_password 默认认证插件会让老应用连接报 Client does not support authentication protocol。
实操建议:
- 删掉
my.cnf里所有 5.7 兼容但 8.0 已废弃的sql_mode项,尤其NO_AUTO_CREATE_USER - 显式加一行:
default_authentication_plugin=mysql_native_password(放在[mysqld]段) -
character_set_server=utf8mb4和collation_server=utf8mb4_0900_ai_ci必须设,否则新建库表默认用新 collation,老表乱码风险高
导入数据前要重置 root 用户认证方式
即使配了 default_authentication_plugin,刚启的 8.0 容器里 root@localhost 用户仍可能沿用 caching_sha2_password——因为系统库是从 5.7 dump 过来的,mysql.user 表里 plugin 字段没变。
实操建议:
- 容器启动后,先连进去:
docker exec -it mysql8 mysql -u root -p - 执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xxx'; - 如果要用
%远程访问,也得补一条:ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx'; - 再
FLUSH PRIVILEGES;,之后用 Navicat、Workbench 或应用代码连才真正生效
mysql_upgrade 这一步没人提醒你必须做,以及 root 用户的认证插件实际值藏在 mysql.user 表里,光改配置文件根本不管用。


















