一、容器存储问题
由于 rootfs 通过联合挂载实现镜像的共享,通过 Copay Or Writer实现数据的读写操作,这导致了 rootfs 在存储上存在很大的问题
- 问题一:读写性能差
如上图,文件的读取需要先到读写层读取,读取不到再到只读镜像中读取文件,读性能差。
如上图,文件的写需要先从只读镜像中 copy 一份出来到读写层,然后进行修改,写性能差。 - 问题二:数据无法永久保存
如上图,读写层随着容器的运行 而存在,随着容器的运行和消亡,数据无法持久化保存。
(如果真的先保存,可以通过 docker commit 的方式,将这个运行中的容器打成镜像进行保存,但这违背了 Docker 镜像快速分发的原则,后期将变成一个个定制化容器,可复用性差,不符合容器轻量化使用原则) - 问题三:数据无法共享
Docker 容器通过 namespace 进行了资源隔离,其中包括了存储隔离,所以各个容器包括宿主机无法共享数据
二、容器卷(volume)
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 卷会一直存在,直到没有容器使用
- 数据卷的使用,类似于 Linux 下对目录或文件进行 mount。
2.1、容器卷引入对数据读写的影响

如图,在没有引入容器卷(volume)之前,容器数据的读写都在镜像的读写层(Aufs、Overlayfs、Btrfs)中,随意会存在之前提到的三个问题
- 读写性能差
- 数据无法共享
- 数据无法持久保存
引入 容器卷(volume)后,相当于将 Docker 宿主机上的文件路径挂载到容器中,容器针对数据的读写都是直接针对 Docker 宿主机文件数据的读写操作,少了读写曾,提高了数据读写性能,同时数据直接写到了 Docker 宿主机,实现了数据持久化,同时数据在宿主机中能够被他容器或者主机访问到,从而实现数据间的共享。
2.2、容器卷挂载方式

Docker 提供了三种方式进行数据卷的挂载
- bind mount
指定 host 主机的完整路径进行挂载 - volume
docker 提供的模块,对Bind mount进行了封装,单纯指定逻辑卷即可 - tmpfs mount
使用宿主机内存进行数据的存储,不直接存储到磁盘中
| 优点 | 缺点 | |
|---|---|---|
| Bind mount | - 使用灵活,能够指定路径 - 容器通过路径直接共享文件/目录 |
需要指定宿主机全路径,并自行进行管理,防止路径冲突 |
| volume | - 针对 bind mount 封装,简化操作,无须关注路径是否冲突 - 通过name实现多容器共享 - 支持挂载远程卷 |
宿主机已有数据无法共享给容器 |
| tmpfs mount | - 读写性能高 - 数据更安全 |
- 无法持久化 - 无法多容器共享 - 消耗内存 |
