记一次 MariaDB 数据恢复:从挂载失误操作中抢救数据库
🧨 事故复盘
某天我发现部署在 Docker Compose 下的 MariaDB 容器没有挂载数据卷。于是我就顺手地在 docker-compose.yml 中加了挂载:

本意是把容器里的数据库同步到宿主机目录 ./mariadb_website/data。
然而忽略了一个Docker 最基础的知识点:
Docker 的挂载是单向的,如果目标目录(宿主机侧)已有内容为空或不存在,会覆盖容器内已有的数据。
于是我愉快地喜提:数据库数据被覆盖清空,WordPress 整站塌了。

🔁 如何恢复
💡 先说结论
Docker 默认会把未挂载的数据目录放在宿主机的 /var/lib/docker/volumes/ 中。
当你没有显式指定 volumes: 时,Docker 会自动为容器的数据目录创建一个匿名 volume,数据库数据就保存在其中。
类似下图所示:

其中 nginx_website 是我显式命名的卷,而 e2b.../_data 就是 Docker 自动创建的匿名卷。
🛠️ 恢复流程
-
找到 MariaDB 的匿名数据卷
查看
/var/lib/docker/volumes/,根据创建时间、大小、**volume 内容结构(是否包含ibdata1、ib_logfile0等)**来判断是否为 MariaDB 数据。
-
将数据复制回新挂载目录
cp -a /var/lib/docker/volumes/db_volume/_data ./mariadb_website/data -
修复权限(MariaDB 容器默认使用 uid 999 的 mysql 用户)
sudo chown -R 999:999 ./mariadb_website/data -
重启
docker compose up -d,WordPress 页面恢复,世界再次美好。
🔍 Docker 挂载机制与底层理解
匿名卷的来源
当容器第一次创建时,如果你没有定义挂载目录,Docker 会在 /var/lib/docker/volumes/ 下自动创建一个匿名卷,挂载到如 /var/lib/mysql。
只有在你 docker rm 或 docker compose down 并使用 --volumes 参数时,该匿名卷才会被删除。
容器的存储结构(OverlayFS 简述)
容器是由以下组成:
- 多层 只读镜像层(Image Layers)
- 一个可写层(Write Layer),也叫diff 层
如果没有挂载卷,数据将写入容器的 diff 层中,一旦容器删除,diff 层也会被删除。
而使用 volume(无论匿名还是命名)可以实现容器之间共享数据,且这里的数据是持久化存储的,volume 生命周期独立于容器。
diff 层能否恢复数据?
理论上,Docker 容器的 diff 层位于 /var/lib/docker/overlay2/<ID>/diff,你可以进去查找,但数据是非结构化的,InnoDB 文件格式复杂、数据碎片化严重。
✅ 结论:diff 层不适合恢复数据库。专业恢复需靠数据快照、数据库导出或挂载卷备份。
✅ 总结 & 建议
| 操作前 checklist ✅ | 注意事项 ⚠️ |
|---|---|
确保 volumes: 明确挂载了数据目录 |
不挂载数据目录会生成匿名卷 |
| 建议使用命名卷,便于管理和恢复 | bind mount 操作失误会覆盖容器内数据 |
定期备份 volume(docker volume backup) |
diff 层 数据无法可靠恢复 |
使用 docker volume inspect 确认挂载路径 |
删除容器不等于删除 volume |
希望本文对你在 Docker + 数据服务部署中踩过的坑能提供一点参考价值。如果你也踩过类似的坑,欢迎评论区交流。
(全文完)





Comments | 3 条评论
我要骂你了.jpg
怎么还在用 root 账户
@AptS:1547 ~~没root我进不去volume里面~~
@AptS:1547 你的rustdesk快发 (・`ω´・)