一、存储特性
默认情况下,容器内创建的所有文件都存储在可写容器层上。这意味着:
当容器不再运行时,数据不会持续存在,并且如果另一个进程需要数据,则很难从容器中获取数据。
容器的可写层紧密耦合到容器运行的主机。您无法轻松地将数据移到其他地方。
写入容器的可写层需要存储驱动程序来管理文件系统。存储驱动程序使用Linux内核提供联合文件系统。与使用直接写入主机文件系统的数据卷相比,这种额外的抽象性能会降低性能。
Docker有两种容器将文件存储在主机中的选项,这样即使在容器停止之后这些文件也会被保留:卷和绑定挂载。
二、图像/容器的存储
1. 图像存储原理
Docker镜像是由一系列图层构建而成的。每个图层代表图像的Dockerfile中的指令。除最后一层以外的每个图层都是只读的。
2. 容器存储原理
容器和图像之间的主要区别是最高的可写层。所有写入容器的添加新的或修改现有数据的内容都存储在该可写层中。当容器被删除时,可写层也被删除。底层图层保持不变。
由于每个容器都有自己的可写容器层,并且所有更改都存储在此容器层中,因此多个容器可以共享对相同基础映像的访问权限,并拥有自己的数据状态。
下图显示了共享相同Ubuntu 15.04映像的多个容器。
3. docker存储操作过程
当你启动一个容器时,一个薄的可写容器层被添加到其他层的顶部。容器对文件系统所做的任何更改都存储在此处。容器不会更改的任何文件都不会被复制到此可写层中。这意味着可写层尽可能小。
当容器中的现有文件被修改时,存储驱动程序执行写入时复制操作。涉及的具体步骤取决于具体的存储驱动程序。对于默认的aufs驱动程序以及overlay和overlay2驱动程序,写入时复制操作遵循以下粗略顺序:
通过图像层搜索要更新的文件。该过程从最新层开始,一次处理一层基础层。找到结果后,它们将被添加到缓存中以加速未来的操作。
对找到的文件的第一个副本执行copy_up操作,将文件复制到容器的可写层。
对该文件的副本进行任何修改,并且该容器不能看到存在于较低层中的文件的只读副本。
4. docker存储的一些注意事项
编写大量数据的容器比不包含数据的容器消耗更多的空间。这是因为大多数写入操作会在容器的可写顶层中占用新的空间。
copy_up操作可能会导致显着的性能开销。这个开销根据使用的存储驱动程序而不同。大文件,大量图层和深层目录树可以使影响更加明显。这可以通过每次copy_up操作仅在第一次修改给定文件时发生。
三、docker支持的几种存储驱动与配置
1. AUFS
https://docs.docker.com/storage/storagedriver/aufs-driver/
2. Btrfs
https://docs.docker.com/storage/storagedriver/btrfs-driver/
3. Device mapper
https://docs.docker.com/storage/storagedriver/device-mapper-driver/#prerequisites
4. OverlayFS
https://docs.docker.com/storage/storagedriver/overlayfs-driver/
5. ZFS
https://docs.docker.com/storage/storagedriver/zfs-driver/
6. VFS
https://docs.docker.com/storage/storagedriver/vfs-driver/
四、持久化的数据存储
1. Volumes
卷存储在由Docker管理的主机文件系统的一部分中(Linux上的/var/lib/docker/volumes/)。 非Docker进程不应该修改这部分文件系统。 卷是在Docker中保留数据的最佳方式。
详细说明与配置
https://docs.docker.com/storage/volumes/#differences-between–v-and—mount-behavior
2. bing-mount
绑定安装可以存储在主机系统的任何位置。 他们甚至可能是重要的系统文件或目录。 Docker主机或Docker容器上的非Docker进程可以随时修改它们。
详细说明与配置
3. tmpfs-mount
tmpfs挂载仅存储在主机系统的内存中,并且永远不会写入主机系统的文件系统。
详细说明与配置
五、docker存储使用到的两种计算机
1. 写时复制(CoW)
所有驱动都用到的计算机——写时复制(CoW)。CoW就是copy-on-write,表示只在需要写时才去复制,这个是针对已有文件的修改场景。比如基于一个image启动多个Container,如果为每个Container都去分配一个image一样的文件系统,那么将会占用大量的磁盘空间。而CoW技术可以让所有的容器共享image的文件系统,所有数据都从image中读取,只有当要对文件进行写操作时,才从image里把要写的文件复制到自己的文件系统进行修改。所以无论有多少个容器共享同一个image,所做的写操作都是对从image中复制到自己的文件系统中的复本上进行,并不会修改image的源文件,且多个容器操作同一个文件,会在每个容器的文件系统里生成一个复本,每个容器修改的都是自己的复本,相互隔离,相互不影响。使用CoW可以有效的提高磁盘的利用率。
2. 用时分配(allocate-on-demand)
而写时分配是用在原本没有这个文件的场景,只有在要新写入一个文件时才分配空间,这样可以提高存储资源的利用率。比如启动一个容器,并不会为这个容器预分配一些磁盘空间,而是当有新文件写入时,才按需分配新空间。
六、参考资料
1. 内容来源
http://dockone.io/article/1513
2. 官方资料
https://docs.docker.com/storage/