一、容器存储问题

由于 rootfs 通过联合挂载实现镜像的共享,通过 Copay Or Writer实现数据的读写操作,这导致了 rootfs 在存储上存在很大的问题
image.png

  • 问题一:读写性能差
    如上图,文件的读取需要先到读写层读取,读取不到再到只读镜像中读取文件,读性能差。
    如上图,文件的写需要先从只读镜像中 copy 一份出来到读写层,然后进行修改,写性能差。
  • 问题二:数据无法永久保存
    如上图,读写层随着容器的运行 而存在,随着容器的运行和消亡,数据无法持久化保存。
    (如果真的先保存,可以通过 docker commit 的方式,将这个运行中的容器打成镜像进行保存,但这违背了 Docker 镜像快速分发的原则,后期将变成一个个定制化容器,可复用性差,不符合容器轻量化使用原则)
  • 问题三:数据无法共享
    Docker 容器通过 namespace 进行了资源隔离,其中包括了存储隔离,所以各个容器包括宿主机无法共享数据

针对存储问题,Docker 提出了容器数据卷概念。

二、容器卷(volume)

数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 卷会一直存在,直到没有容器使用
  • 数据卷的使用,类似于 Linux 下对目录或文件进行 mount。

2.1、容器卷引入对数据读写的影响

image.png
如图,在没有引入容器卷(volume)之前,容器数据的读写都在镜像的读写层(Aufs、Overlayfs、Btrfs)中,随意会存在之前提到的三个问题

  • 读写性能差
  • 数据无法共享
  • 数据无法持久保存

引入 容器卷(volume)后,相当于将 Docker 宿主机上的文件路径挂载到容器中,容器针对数据的读写都是直接针对 Docker 宿主机文件数据的读写操作,少了读写曾,提高了数据读写性能,同时数据直接写到了 Docker 宿主机,实现了数据持久化,同时数据在宿主机中能够被他容器或者主机访问到,从而实现数据间的共享。

2.2、容器卷挂载方式

01.png
Docker 提供了三种方式进行数据卷的挂载

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

- 无法持久化
- 无法多容器共享
- 消耗内存

2.3、案例

Volumes-数据卷案例
Volumes-数据容器卷案例