Docker 数据卷持久化原理

Docker 数据卷持久化原理

一、为什么容器数据会丢失

容器的文件系统是分层的可写层,容器删除后可写层一并销毁。如果把数据库文件、上传的图片直接写在容器内部,一旦容器重启、重建或删除,数据就没了。持久化就是把数据存到容器之外的宿主机或独立存储,让容器变成可随时替换的无状态单元,这是 Docker 生产部署的核心要求。

二、三种持久化方式对比

Docker 提供三种方式把宿主机目录映射进容器,适用场景不同:

1. bind mount(绑定挂载)

直接把宿主机指定目录挂进容器,路径完全由用户控制:

docker run -d \
  -v /host/data:/var/lib/mysql \
  mysql:8.0

适合把已有配置、上传目录直接暴露到宿主机,缺点是强依赖宿主机目录结构,跨机器迁移麻烦。

2. named volume(命名数据卷)

由 Docker 管理目录,不用关心宿主机具体路径:

docker volume create mysql_data
docker run -d -v mysql_data:/var/lib/mysql mysql:8.0

数据卷由 Docker daemon 管理,可被多个容器共享,备份迁移方便,是数据库首选。

3. tmpfs mount(内存挂载)

数据只存内存,不写磁盘,容器停止即消失,适合临时缓存、敏感密钥,不用于持久化。

三、挂载原理

bind mount 和 volume 在 Linux 底层都通过 mount namespace 实现:容器看到的 /var/lib/mysql 实际指向宿主机对应目录,写入时落到宿主机磁盘,绕过容器分层文件系统。多个容器挂载同一个数据卷时,读写同一份数据,实现共享。

四、docker-compose 写法

多容器项目在 compose 文件里声明数据卷:

version: "3"
services:
  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql
      - ./my.cnf:/etc/mysql/conf.d/my.cnf:ro
volumes:
  db_data:

db_data 是命名卷,./my.cnf 是只读绑定挂载配置文件。

五、备份与迁移

命名卷备份:

docker run --rm -v mysql_data:/src -v $(pwd):/backup \
  alpine tar czf /backup/db.tar.gz -C /src .

用临时容器把数据卷打包,再在新机器解包恢复,实现跨主机迁移。

六、常见误区

  1. 把数据库文件放在容器内,删容器丢数据;
  2. bind mount 权限不匹配,容器内用户读不到文件;
  3. 多个容器同时写同一卷不加锁,造成数据竞争;
  4. 只读配置文件没加 :ro,容器误写宿主机文件;
  5. 忘记定期备份数据卷,磁盘损坏无法恢复。

七、总结

持久化让容器与数据解耦:数据库、上传目录用命名卷,配置文件用只读绑定挂载,临时数据用 tmpfs。理解挂载底层是宿主机目录映射,配合 compose 声明和 tar 备份迁移,就能保证容器重建不丢数据,实现真正的弹性伸缩。


emer 发布于  2026-11-14 07:20 
'); })();