最推荐使用docker volume create创建命名卷挂载到/var/lib/mysql,因其由docker自动处理权限、selinux及兼容性;必须挂载该路径,因mysql官方镜像硬编码datadir为/var/lib/mysql,挂错则初始化失败、数据丢失。

docker volume create 是最省心的起点,命名卷方式能避开 90% 的权限、SELinux 和文件系统兼容性问题。直接挂载宿主机目录看似可控,但实际踩坑成本远高于收益。
为什么必须挂载 /var/lib/mysql?
MySQL 官方镜像硬编码了数据目录路径,datadir 值写死为 /var/lib/mysql,改环境变量或配置文件都无效。挂错路径(比如 /data 或 /mysql)会导致:
- 容器反复重启,
docker logs报Can't read dir of '/var/lib/mysql/' (Errcode: 2) - 首次能连上,新建库表后重启就消失——说明挂载根本没生效
-
docker exec -it mysql ls /var/lib/mysql返回空,证实数据没写进去
命名卷 vs 宿主机目录挂载:选哪个?
命名卷是官方推荐且更稳妥的选择,Docker 自动处理 UID/GID、SELinux 上下文、文件系统优化;绑定挂载只在两类场景真正必要:
- 需要脚本直接读取
.ibd或ibdata1文件做物理备份(注意:不一致风险高) - 开发时频繁修改配置并希望实时看到效果(此时仍建议用
/etc/mysql/conf.d/挂载子目录,而非整个/etc/mysql)
若坚持用宿主机目录,务必:
- 提前执行
sudo mkdir -p /mydata/mysql && sudo chown -R 999:999 /mydata/mysql - SELinux 启用时加
:Z标签:-v /mydata/mysql:/var/lib/mysql:Z - 绝对不用 NFS/CIFS 共享目录——MySQL 不支持网络文件系统作为数据目录
环境变量和初始化 SQL 只在首次生效
MYSQL_ROOT_PASSWORD、MYSQL_DATABASE 等变量仅在 /var/lib/mysql 目录为空时触发初始化流程。一旦该目录已有内容(哪怕只是个空文件),容器就会跳过初始化,所有环境变量被忽略。
- 常见误操作:删容器重跑,但没清空宿主机挂载目录 → 密码还是旧的
- 想重置初始化,得手动清空挂载路径(命名卷用
docker volume rm,宿主机目录用rm -rf /mydata/mysql/*) - 预置 SQL 脚本应放
/docker-entrypoint-initdb.d/,文件需.sql或.sh后缀,且仅在初始化阶段执行
自定义配置怎么才生效?
挂载配置文件不能只丢一个 my.cnf 进 /etc/mysql/conf.d/,必须满足两个条件:
- 文件路径正确:
-v /host/conf.d:/etc/mysql/conf.d(整个目录挂载)或-v /host/my.cnf:/etc/mysql/my.cnf(全路径覆盖) - 内容含
[mysqld]段,且参数兼容 MySQL 8.0(如default_authentication_plugin=mysql_native_password必须显式设置,否则 Navicat/JDBC 连不上)
验证是否生效:docker exec mysql-container mysql -uroot -p -e "SHOW VARIABLES LIKE 'datadir';",输出必须与挂载路径完全一致。
datadir 是否真被 MySQL 读取、也没人确认初始化是否真的发生了——这两点漏掉,持久化就形同虚设。











