理解Docker镜像分层 (2)

第一列是imageid, 最上面的id就是我们新创建ryan/httpd:latest. 下面几行都是我们dockerfile里定义的步骤堆栈。由此可以看出,每个步骤都将创建一个imgid, 一直追溯到1e1148e4cc2c正好是我们的base镜像的id。关于<missing>的部分,则不在本机上。

最后一列是每一层的大小。最后一层只是启动bash,所以没有文件变更,大小是0. 我们创建的镜像是在base镜像之上的,并不是完全复制一份base,然后修改,而是共享base的内容。这时候,如果我们新建一个新的镜像,同样也是共享base镜像。

那修改了base镜像,会不会导致我们创建的镜像也被修改呢? 不会!因为不允许修改历史镜像,只允许修改容器,而容器只可以在最上面的容器层进行写和变更。

容器的大小

创建镜像的时候,分层可以让docker只保存我们添加和修改的部分内容。其他内容基于base镜像,不需要存储,读取base镜像即可。如此,当我们创建多个镜像的时候,所有的镜像共享base部分。节省了磁盘空间。

对于启动的容器,查看所需要的磁盘空间可以通过docker ps -s

# docker run -d -it centos 4b0df4bc3e705c540144d545441930689124ade087961d01f56c2ac55bfd986d # docker ps -s | grep -E '(ryan|centos)' 4b0df4bc3e70 centos "/bin/bash" 23 seconds ago Up 23 seconds vigorous_elion 0B (virtual 202MB) b36421d05005 ryan/httpd:v1.0 "/usr/sbin/init" 32 minutes ago Up 32 minutes gracious_swirles 61.6kB (virtual 444MB)

首先启动一个base镜像用来对比

可以看到第一行就是base镜像centos,第2列的size是0和202MB, 0表示容器层可写层的大小,virtual则是容器层+镜像层的大小。这里对比可以看到一共202M,正好是最初centos镜像的大小。

第二行是我们自己创建的镜像。virtual达到了444MB。对比前面的history部分,可以发现这个数字是每一层大小之和。同时,由于共享base,其中的202M是和第一行的镜像共享的。

修改时复制策略 copy-on-write (CoW)

docker通过一个叫做copy-on-write (CoW) 的策略来保证base镜像的安全性,以及更高的性能和空间利用率。

Copy-on-write is a strategy of sharing and copying files for maximum efficiency. If a file or directory exists in a lower layer within the image, and another layer (including the writable layer) needs read access to it, it just uses the existing file. The first time another layer needs to modify the file (when building the image or running the container), the file is copied into that layer and modified. This minimizes I/O and the size of each of the subsequent layers. These advantages are explained in more depth below.

Copying makes containers efficient

When you start a container, a thin writable container layer is added on top of the other layers. Any changes the container makes to the filesystem are stored here. Any files the container does not change do not get copied to this writable layer. This means that the writable layer is as small as possible.

When an existing file in a container is modified, the storage driver performs a copy-on-write operation. The specifics steps involved depend on the specific storage driver. For the aufs, overlay, and overlay2 drivers, the copy-on-write operation follows this rough sequence:

Search through the image layers for the file to update. The process starts at the newest layer and works down to the base layer one layer at a time. When results are found, they are added to a cache to speed future operations.

Perform a copy_up operation on the first copy of the file that is found, to copy the file to the container’s writable layer.

Any modifications are made to this copy of the file, and the container cannot see the read-only copy of the file that exists in the lower layer.

Btrfs, ZFS, and other drivers handle the copy-on-write differently. You can read more about the methods of these drivers later in their detailed descriptions.

Containers that write a lot of data consume more space than containers that do not. This is because most write operations consume new space in the container’s thin writable top layer.

简单的说,启动容器的时候,最上层容器层是可写层,之下的都是镜像层,只读层。

当容器需要读取文件的时候

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwgyf.html