Docker storage driver(十四)
一、storage driver 作用
正常情况下,只有很少量的数据被写入到容器最上层的写入层,并且通过 volume 来写数据,然而我们也会遇到一些情况需要我们可以直接写入到容器的写入层,这我们就需要到了 storage driver 来帮忙。
Docker 使用一些列不同的 storage driver 来管理镜像层和容器层,这些 storage driver 不同于前面说到的 volume。
为了有效的使用 storage drivers,我们可以简单温习一下 storage driver 管理的镜像层和容器层的工作情况。
1、Images and layers
我们可以通过下面的 Dockerfile 文件来理解镜像的分层。
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
- 一个镜像是有若干镜像层组成。
- Dockerfile 中的每条指令都会生成一个镜像层,除了最上面的一层之外,其他的都是只读的。
- 最上一层主要是镜像运行时的一些命令。
- 每一层只是与它之前的层有一些不同,层层堆叠在一起。
- 创建容器的时候,只是在底层上添加一个新的可写层。这一层通常称为“容器层”。
2、Container and layers
容器和镜像最大的区别在于最上层的可写层,所有对容器的新增或者修改,都会存在在可写层,当容器被删除的时候,可写层的数据也就随之被删除了,然后镜像的不会改变。
这是因为每个容器都有自己的可写层,所有的更改都会存储在容器的可写层,多个容器可以共享对同一底层映像的访问,但他们都拥有自己的数据状态,如下图所示:
Copy-on-Write
容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存放在这些层中。这样的分层结构最大的特性是 Copy-on-Write:
- 新数据会直接存放在最上面的容器层。
- 修改现有数据会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,镜像层保持不变。
- 如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。
分层结构使镜像和容器的创建、共享以及分发变得非常高效,而这些都要归功于 Docker storage driver。正是 storage driver 实现了多层数据的堆叠并为用户提供一个单一的合并之后的统一视图。
3、Data volumes and the storage driver
Data Volume 本质上是 Docker Host 文件系统中的目录或文件,能够直接被 mount 到容器的文件系统中。Data Volume 有以下特点:
- Data Volume 是目录或文件,而非没有格式化的磁盘(块设备)。
- 容器可以读写 volume 中的数据。
- volume 数据可以被永久的保存,即使使用它的容器已经销毁。
- Data volumes 不被 storage driver 所管理。
- 对 data volume 的读写操作绕过 storage driver,以本地主机速度运行。
二、如何选择 storage driver
Docker 支持多种 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它们都能实现分层的架构,同时又有各自的特性。对于 Docker 用户来说,具体选择使用哪个 storage driver 是一个难题。
下表是官方根据不同的发行版支持推荐的 storage driver。
Linux 发行版 | 推荐的storage drivers |
---|---|
Docker CE on Ubuntu | aufs, devicemapper, overlay2 (Ubuntu 14.04.4 or later, 16.04 or later), overlay, zfs, vfs |
Docker CE on Debian | aufs, devicemapper, overlay2 (Debian Stretch), overlay, vfs |
Docker CE on CentOS | devicemapper, vfs |
Docker CE on Fedora | devicemapper, overlay2 (Fedora 26 or later, experimental), overlay (experimental), vfs |
不过 Docker 官方给出了一个简单的答案:
优先使用 Linux 发行版默认的 storage driver。
Docker 安装时会根据当前系统的配置选择默认的 driver。默认 driver 具有最好的稳定性,因为默认 driver 在发行版上经过了严格的测试。
运行docker info
查看 Ubuntu 的默认 driver:
root@ubuntu:~# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 19
Server Version: 17.09.0-ce
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Redhat/CentOS 的默认 driver 是 Device Mapper,SUSE 则是 Btrfs。
对于某些容器,直接将数据放在由 storage driver 维护的层中是很好的选择,比如那些无状态的应用。无状态意味着容器没有需要持久化的数据,随时可以从镜像直接创建。
比如 busybox,它是一个工具箱,我们启动 busybox 是为了执行诸如 wget,ping 之类的命令,不需要保存数据供以后使用,使用完直接退出,容器删除时存放在容器层中的工作数据也一起被删除,这没问题,下次再启动新容器即可。
但对于另一类应用这种方式就不合适了,它们有持久化数据的需求,容器启动时需要加载已有的数据,容器销毁时希望保留产生的新数据,也就是说,这类容器是有状态的。这就需要我们使用 volume。
参考文档:https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/
https://docs.docker.com/engine/userguide/storagedriver/selectadriver/