本文次要介绍Docker容器(Container)和镜像(Image)是如何进行数据存储的。
容器如何读写文件
镜像(Image)是由若干个层(Layer)所组成的,当用户应用image运行了一个container之后,就会在这个image的最下面再加上一个可读可写的layer,如下图所示:
除了最下面那一个layer是可读写的之外,上面的所有layer都是属于image的,都是只读的。
在container运行时,任何在container文件系统中写入和批改的数据都会被写入到最上层的可读写layer(这里不包含volume、bind mount和tmpfs这些长久化存储伎俩),并不会影响到上面的那些只读layer。当container运行完结的时候,最上层的可读写layer就会被抛弃,而上面的那些只读layer是属于image的,并不会受到影响。
这也就是为什么应用同一个image运行container,该container完结之后,从新应用该image启动一个新的container,上一个container写入和批改的数据全都不见了,用户能看见的仍旧是当初编写Dockerfile时写入该image的那些数据的起因。
如果应用同一个image启动了多个container,那么这些container会有各自的最上层的可读写layer,然而上面的那些只读layer是共用的,如下图所示:
镜像的layer治理
一个image的多个layer并不是绑定和存储在一起的,它们之间是低耦合的。
应用docker pull
命令拉取一个image的时候,并不是一次性拉取的,而是一个layer一个layer地拉取,而后存储在本机(在linux上默认是/var/lib/docker/<storage-driver>/
下)。
一台主机中存在多个image时,有可能会呈现多个image的某些layer雷同的状况,那么此时在主机中就只会存储一份该layer,而不是存储多个。
那么问题来了:既然多个layer是离开存储的,那么用户在container中却能够看到所有的layer中存储的文件,这又是怎么做到的呢?这就波及到了union file system和union mount。
能够通过docker image history
以及docker image inspect
来查看某个image的所有layer。
Copy On Write
当container想要更改本来就存在于image中的那些数据的时候该怎么办呢?那些数据是位于下面那些属于image的只读层的,因而必定不能间接批改。Docker采纳的解决方案个别是copy-on-write。
当container想要读取本来就存在于image中的数据时,间接从数据所在的只读layer读取即可。而如果想要批改本来就存在于image中的数据时,Docker就会先把要被批改的文件拷贝到最上层的属于container的可读写layer中,而后再在这个可读写的layer中进行数据的批改即可。
值得一提的是,哪怕是对文件的元数据(meta data)的批改(例如批改文件权限、所属用户等等),也会触发copy-on-write机制。
Docker有多种存储引擎(storage driver),不同的storage driver对copy-on-write的具体实现是不一样的。
留神:并不是所有的Docker存储引擎都反对copy on write的,例如vfs就不反对!
查看容器占用磁盘大小
应用docker ps -s
来查看一个container在运行时占用的磁盘大小,例如:SIZE
指的是该container最上层的可读写layer的大小,而virtual
指的是启动了该container的image的那些只读layer的大小。
须要留神的是,通过这个命令失去的container磁盘空间大小是不包含以下这些的:
- log文件所应用的磁盘空间
- volume和bind mount所应用的磁盘空间
- container的配置文件所应用的磁盘空间
- 内存交换所应用的磁盘空间
- Checkpoints所应用的磁盘空间
Docker存储引擎
Docker在linux下提供了如下的存储引擎选项:
存储引擎 | 形容 |
---|---|
overlay2 | 在linux上首选的存储引擎,不须要额定的配置 |
fuse-overlayfs | 举荐在运行rootless的Docker时应用 |
btrfs和zfs | 能够提供更多的性能,例如快照等等,然而须要额定的配置 |
vfs | 目前仍处于测试中,用于不反对copy on write的文件系统中,性能堪忧,不举荐应用在生产环境中 |
devicemapper | 在生产环境中须要direct-lvm的反对 |
能够通过docker info
命令来查看本人应用的Docker用的是哪一个storage driver:
上图中应用的storage driver是overlay2。
参考资料
https://docs.docker.com/storage/storagedriver/