必须挂载/var/lib/mysql到宿主机绝对路径,否则容器删除后数据彻底丢失;需创建目录并设属主999:999,用-v挂载,且仅当该目录为空时mysql_root_password等环境变量才生效。

必须挂载 /var/lib/mysql 到宿主机绝对路径
不挂这个路径,容器删了数据就彻底消失——MySQL 8.0 官方镜像硬编码所有数据(系统库、表空间、redo log、undo log)都写在 /var/lib/mysql 下,临时文件系统里存不住。
常见错误现象包括:容器卡在 Initializing database、日志报 Can't open the mysql.plugin table、或者启动后连不上 root;90% 是因为挂载路径为空父目录(如 /mydata),或目录属主是 root 而不是 UID 999。
- 先创建目录:
sudo mkdir -p /mydata/mysql/data - 再设属主:
sudo chown -R 999:999 /mydata/mysql/data(不能用chmod 777) - 启动时用
-v /mydata/mysql/data:/var/lib/mysql,路径必须是绝对路径,./data或~/data无效 - 如果宿主机目录已有旧数据,确认是同版本 MySQL 8.x 生成的,否则可能因数据字典变更直接拒绝启动
/etc/mysql/conf.d/ 是唯一推荐的配置挂载点
MySQL 8.0 容器按顺序加载:/etc/mysql/my.cnf → /etc/mysql/conf.d/*.cnf → /etc/mysql/mysql.conf.d/*.cnf。官方镜像不鼓励覆盖 my.cnf,升级时容易丢配置;而 conf.d/ 下的 .cnf 文件会被自动识别并合并生效,更安全可控。
字符集、插件、连接数等关键配置都该放这儿。比如中文乱码或 Illegal mix of collations 错误,基本是因为没挂对位置或内容格式不对。
- 在宿主机建文件:
/mydata/mysql/conf/01-charset.cnf - 内容必须含
[mysqld]段,例如:[mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci [client] default-character-set=utf8mb4
- 启动时挂载:
-v /mydata/mysql/conf:/etc/mysql/conf.d:ro(加:ro防误写) - 文件名建议加数字前缀(如
01-),避免字母序靠后的配置被覆盖
MYSQL_ROOT_PASSWORD 只在首次初始化时起作用
环境变量不是“每次启动都重设”,而是仅当 /var/lib/mysql 目录为空时才触发初始化流程。一旦目录里有残留(哪怕只是个空 ibdata1 或中断留下的半初始化文件),MySQL 就跳过初始化,直接加载现有数据——此时你改任何 MYSQL_* 环境变量都没用。
典型表现:密码还是上次的、MYSQL_DATABASE 没自动建库、日志里看不到 Initializing database 字样。
- 检查方式:
ls -la /mydata/mysql/data,非空即跳过初始化 - 想重置:只能清空目录(
sudo rm -rf /mydata/mysql/data && sudo mkdir -p /mydata/mysql/data && sudo chown -R 999:999 /mydata/mysql/data) - 生产环境别依赖这个机制做密码轮换,该用
ALTER USER显式修改
日志和备份路径也得挂,但优先级低于数据目录
/var/log/mysql 和 /etc/mysql/conf.d 不挂不影响启动,但会损失可观测性和可维护性。尤其日志——docker logs mysql8 只输出启动阶段 stdout,真正慢查询、连接拒绝、权限错误全在 /var/log/mysql/error.log 里。
备份也不能依赖容器内 cron:MySQL 官方镜像不带 cron,也不该塞备份脚本进去。备份动作必须由宿主机发起,且目标路径必须是宿主机磁盘。
- 日志挂载示例:
-v /mydata/mysql/logs:/var/log/mysql - 备份命令必须从宿主机执行:
docker exec mysql8 mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --all-databases | gzip > /backup/mysql-$(date +\%F).sql.gz - 密码别硬编码进 crontab,用
~/.my.cnf映射进容器更安全
最常被忽略的是属主和初始化时机:目录存在 ≠ 可用,非空 ≠ 可复用。挂载本身很简单,但 MySQL 8.0 对文件系统状态极其敏感,错一个条件就卡住或静默失效。











