Volume 本质是通过 Linux mount 系统调用将宿主机目录(如 /var/lib/docker/volumes/myvol/_data)直接挂载到容器路径,绕过 UnionFS,实现数据持久化、共享与生命周期独立;相比 Bind Mount,它由 Docker 自动管理路径与权限,更安全可移植,适用于生产环境。

Volume 绕过联合文件系统(UnionFS),本质是把数据直接写进宿主机磁盘,不经过容器的可写层。它不是镜像层的叠加或临时修改,而是从一开始就把容器内某个路径“映射”到宿主机上一个真实目录,所有读写操作都落在这个目录里。
为什么需要绕过 UnionFS?
容器默认使用 UnionFS(如 overlay2)组织文件系统:镜像层只读,容器启动时叠加一层可写层。但这一层随容器删除而销毁——数据就丢了。Volume 跳过这整套机制,让应用往 /var/lib/postgresql/data 写数据时,实际写的是宿主机 /var/lib/docker/volumes/myvol/_data,和容器生命周期完全解耦。
Volume 是怎么做到“绕过”的?
Docker 在创建容器时,通过 Linux 的 mount 系统调用,把一个宿主机目录(比如 /var/lib/docker/volumes/db-data/_data)以 bind mount 方式挂载到容器内指定路径(如 /var/lib/postgresql/data)。这个挂载点在容器命名空间里可见,但底层 I/O 直接走宿主机文件系统,UnionFS 完全不参与。
- 镜像自带的初始化数据(如 PostgreSQL 的初始数据库文件)会在**首次挂载空卷**时,被自动复制进该目录;之后所有变更都在这里发生
- 容器进程调用 open()、write() 等系统调用,内核直接路由到宿主机对应路径,不经过 overlay 可写层
- 即使容器崩溃、重启或被 docker rm 删除,只要卷没删,目录和里面的数据就一直存在
和 Bind Mount 有什么区别?
两者都绕过 UnionFS,但 Volume 由 Docker 管理路径和权限,位置固定(/var/lib/docker/volumes/),不依赖用户手动创建目录;Bind Mount 则是用户指定任意宿主机路径(比如 /home/user/app/data),Docker 不管它是否存在、有没有权限、甚至是不是 NFS 挂载点。
- Volume 更安全、可移植,适合生产环境部署数据库或状态服务
- Bind Mount 更灵活,适合开发时热更新代码或共享配置文件
- 两者都能实时双向同步,但 Volume 隐含了初始化复制行为,Bind Mount 没有
关键验证点:数据真的没走容器层?
可以这样验证:
- 运行 docker run -v myvol:/data nginx,然后 docker exec 进去 touch /data/hello.txt
- 执行 docker volume inspect myvol,找到 Mountpoint 字段(如 /var/lib/docker/volumes/myvol/_data)
- 在宿主机上 ls /var/lib/docker/volumes/myvol/_data,能看到 hello.txt
- 删掉容器再重跑一个挂同一卷的容器,/data/hello.txt 依然存在
- 对比:如果不用 -v,只在容器里 touch /tmp/hello.txt,容器删掉后文件就没了


















