必须挂载 /var/lib/mysql,因mysql官方镜像硬编码该路径,挂错则初始化失败且写入无效;宿主机目录须 chown -r 999:999 赋权,首次挂载空目录自动初始化,非空目录跳过初始化并需注意版本兼容性。

必须挂载 /var/lib/mysql,挂错路径等于没挂
MySQL 官方镜像硬编码数据目录为 /var/lib/mysql,改环境变量、配文件、启动参数都无效。挂成 /data 或 /mysql 看似合理,实际会导致容器初始化空库,但所有写入操作失败——日志里反复报 mysqld: Can't read dir of '/var/lib/mysql/' (Errcode: 2)。
常见错误现象:
-
docker exec -it mysql ls /var/lib/mysql返回空,说明挂载根本没生效 - 能连上数据库,建库建表后重启容器,数据全丢
- 容器反复 CrashLoopBackOff,
docker logs mysql显示权限拒绝或目录不存在
宿主机目录挂载前必须 chown -R 999:999
MySQL 容器默认以系统用户 mysql(UID 999)运行,宿主机目录若属主不是 999,容器启动时会因权限不足直接退出。
实操步骤:
- 提前创建目录:
sudo mkdir -p /mydata/mysql - 强制赋权:
sudo chown -R 999:999 /mydata/mysql(注意是-R,不是-r) - 启动时用
-v /mydata/mysql:/var/lib/mysql,不要加 trailing slash - Linux 上 SELinux 开启时,得加
:z标签:-v /mydata/mysql:/var/lib/mysql:z
Windows/macOS Docker Desktop 用户注意:绑定挂载可能因文件系统缓存导致 MySQL 启动失败,命名卷更稳。
首次挂载空目录会自动初始化,已有数据要小心版本兼容
这是设计行为,不是 bug:如果宿主机目录为空,MySQL 容器会执行初始化流程(生成 ibdata1、mysql 系统库等);如果目录里已有旧数据,容器会跳过初始化,直接尝试加载——此时若 MySQL 镜像版本与旧数据不兼容(比如从 5.7 升级到 8.0),大概率启动失败,日志里出现 Unknown table engine 'InnoDB' 或 Table 'mysql.user' doesn't exist。
安全做法:
- 升级前先停容器,用
mysqldump导出逻辑备份 - 换新版本容器 + 新空目录重新导入
- 别指望直接复用老数据目录“无缝升级”
初始化 SQL 脚本必须放 /docker-entrypoint-initdb.d/
只挂数据目录不够,你还想让容器首次启动时自动建库、建表、插初始数据?官方镜像只认这个固定路径下的 .sql 或 .sh 文件。
常见踩坑点:
- 脚本放错位置(如
/init.sql),日志显示Skipping initialization - 脚本语法错误(比如少个分号),MySQL 卡住不动,
docker logs里有ERROR 1064 - 挂载了非空数据目录,整个初始化流程被跳过——哪怕脚本放对位置也没用
正确命令示例:docker run -v ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro -v /mydata/mysql:/var/lib/mysql mysql:8.0











