在 Docker 中,图像是只读图像层的堆栈。我们也知道图像共享图层或其他图像。我的问题是关于这种共享机制是如何工作的。
图像是否具有指向 Docker 存储驱动程序的指针,或者它们实际上是否包含其他层?如果第一个是真的,这是否意味着 Dockerfile 将这些层保存到守护进程中,并且图像是有序检索这些层的指令?
在 Docker 中,图像是只读图像层的堆栈。我们也知道图像共享图层或其他图像。我的问题是关于这种共享机制是如何工作的。
图像是否具有指向 Docker 存储驱动程序的指针,或者它们实际上是否包含其他层?如果第一个是真的,这是否意味着 Dockerfile 将这些层保存到守护进程中,并且图像是有序检索这些层的指令?
这取决于您的存储驱动程序:
Docker 使用存储驱动来管理镜像层和可写容器层的内容。
每个存储驱动程序以不同的方式处理实现,但所有驱动程序都使用可堆叠的图像层和写时复制 (CoW) 策略。Copy-on-write 是一种共享和复制文件以实现最大效率的策略。
- 如果一个文件或目录存在于镜像中的较低层,并且另一个层(包括可写层)需要对其进行读取访问,则它只使用现有文件。
- 其他层第一次需要修改文件时(构建镜像或运行容器时),文件被复制到该层并修改。这最大限度地减少了 I/O 和每个后续层的大小。
现在,在运行时:
启动容器时,会在其他层之上添加一个薄的可写容器层。容器对文件系统所做的任何更改都存储在这里。容器未更改的任何文件都不会复制到此可写层。这意味着可写层尽可能小。
当容器中的现有文件被修改时,存储驱动程序会执行写时复制操作。涉及的具体步骤取决于特定的存储驱动程序。
默认驱动程序是aufs
,overlay
和overlay2
驱动程序。
但是 Btrfs、ZFS 和其他驱动程序以不同的方式处理写时复制。
但无论如何,CoW 仍然是关键:
写时复制不仅节省空间,而且还减少了启动时间。当你启动一个容器(或同一个镜像的多个容器)时,Docker 只需要创建瘦可写容器层。
如果 Docker 每次启动新容器时都必须制作底层镜像堆栈的完整副本,那么容器启动时间和使用的磁盘空间将显着增加。
在“选择存储驱动程序”中查看更多信息。