记一次 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快发 (・`ω´・)