mysql容器重启丢数据主因是误用匿名卷而非命名卷;必须用-v mysql-data:/var/lib/mysql格式挂载命名卷,其生命周期独立于容器,可确保数据持久化。

不是“重启丢数据”,而是挂载没生效——90%的情况,你用的是匿名卷,不是命名卷。
为什么 docker run -v /var/lib/mysql 一重启就丢数据?
这个写法本质是创建匿名卷,每次 docker run 都会生成一个新卷,旧数据被彻底隔离。容器删了、docker-compose down & up、甚至只是 docker restart 后再进容器查,都会发现 /var/lib/mysql 是空的。
- 执行
docker volume ls,看到一堆随机哈希名(如8a7f2b1e4c9d),没有你指定的卷名 → 典型匿名卷 -
docker inspect mysql | grep Mounts显示"Source": "/var/lib/docker/volumes/8a7f2b1e4c9d/_data"→ 数据落在不可控路径 - MySQL 启动时发现
/var/lib/mysql是空目录,就会初始化一套全新库,覆盖你的认知
必须用 mysql-data:/var/lib/mysql 这种命名卷格式
命名卷由 Docker daemon 统一管理,生命周期独立于容器。只要卷名固定,无论容器删多少次、重建多少次,数据都在。
- 提前创建:
docker volume create mysql-data - 启动时显式挂载:
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -v mysql-data:/var/lib/mysql -p 3306:3306 mysql:8.0 - 验证是否生效:
docker volume inspect mysql-data→ 看Mountpoint路径是否存在且非空 -
-v左边不能是路径(如/path/to/data),也不能省略(如-v /var/lib/mysql),必须是卷名:容器内路径
别用绑定挂载(-v $(pwd)/mysql_data:/var/lib/mysql)跑 MySQL 生产环境
看似能持久,实际踩坑极多:
- 宿主机目录权限不对:MySQL 容器内默认用
mysql用户(UID 999)运行,宿主机目录需属主为999:999,否则启动失败或数据损坏 - Mac / Windows 文件系统不兼容 InnoDB 日志刷盘行为,极易损坏
ib_logfile0或ibdata1 - 路径随
pwd变化,docker-compose.yml移动后挂载失效 - 无法跨平台迁移,
docker volume ls看不到,备份恢复难定位
已经用了匿名卷,怎么抢救现有数据?
别删容器!先停服务再导出:
- 停止写入:
docker exec -it mysql mysql -uroot -p -e "SET GLOBAL read_only = ON;" - 导出数据:
docker exec -it mysql mysqldump -uroot -p --all-databases > backup.sql - 新建命名卷并启动新容器:
docker volume create mysql-data-new && docker run -d --name mysql-new -v mysql-data-new:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0 - 导入数据:
docker exec -i mysql-new mysql -uroot -p - 清理无用匿名卷:
docker volume prune(确认无其他容器依赖后再执行)
真正容易被忽略的是:挂载点是否真实落到 /var/lib/mysql —— 很多人以为加了 -v 就万事大吉,但 docker inspect 里 Mounts 的 Destination 字段才是唯一真相。











