容器镜像包含一个打包的应用程序、它的依赖项,以及有关它在启动时运行的进程的信息。容器是当今IT运营的重要组成部分。容器映像包含打包的应用程序、其依赖项以及有关它在启动时运行的进程的信息。您可以通过提供一组特殊格式的指令来创建容器镜像,这些指令可以提交到注册表或保存为Dockerfile。例如,这个Dockerfile为PHPWeb应用程序创建了一个容器:FROMregistry.access.redhat.com/ubi8/ubi:8.1RUNyum--disableplugin=subscription-manager-ymoduleenablephp:7.3\&&yum--disableplugin=subscription-manager-yinstallhttpdphp\&&yum--disableplugin=subscription-managercleanallADDindex.php/var/www/htmlRUNsed-i's/Listen80/Listen8080/'/etc/httpd/conf/httpd.conf\&&sed-i's/listen.acl_users=apache,nginx/listen.acl_users=/'/etc/php-fpm.d/www.conf\&&mkdir/run/php-fpm\&&chgrp-R0/var/log/httpd/var/run/httpd/run/php-fpm\&&chmod-Rg=u/var/log/httpd/var/run/httpd/run/php-fpmEXPOSE8080USER1001CMDphp-fpm&httpd-DFOREGROUND该文件中的每条指令都会为容器镜像添加一层layer。每一层只增加与下一层的差异,然后,所有这些堆叠在一起形成一个只读的容器镜像。它是如何工作的?关于容器镜像,您需要了解一些事情,按顺序理解这些概念很重要:联合文件系统Copy-on-Write(COW)覆盖文件系统快照联合文件系统联合文件系统(UnionFS)构建进入Linux内核,它允许一个文件系统的内容与另一个文件系统的内容合并,同时保持“物理”内容分离。结果是一个统一的文件系统,即使数据实际上是按分支组织的。这里的想法是,如果您有多个图像和一些相同的数据,而不是再次复制该数据,而是通过使用称为层的东西共享。UnionFS的每一层都是一个文件系统,可以在多个容器中共享。例如,httpd基础层是Apache的官方镜像,可以在任意数量的容器中使用。想象一下,由于我们在所有容器中使用相同的基础层,我们节省了多少磁盘空间。这些图像层始终是只读的,但是当我们用这个图像创建一个新容器时,我们在它上面添加了一个薄的可写层。这个可写层是您创建、修改、删除或进行每个容器所需的其他修改的地方。写时复制(COW)当您启动一个容器时,它看起来好像该容器拥有自己的整个文件系统。这意味着您在系统上运行的每个容器都需要自己的文件系统副本。这不会占用大量磁盘空间并且容器启动也需要很多时间吗?不,因为每个容器都不需要自己的文件系统副本!容器和图像使用写时复制(COW)机制来实现这一点。copy-on-write策略不是复制文件,而是将同一个数据实例共享给多个进程,只有当一个进程需要修改或写入数据时才进行复制。所有其他进程将继续使用原始数据。Docker对图像和容器都使用写时复制机制。为了做到这一点,图像和正在运行的容器之间的变化在旧版本中由图形驱动程序跟踪,现在由快照器跟踪。在正在运行的容器中执行任何写入操作之前,将要修改的文件的副本放置在容器的可写层上。这是写作发生的地方。现在你知道为什么它被称为“写时复制”了。该策略优化了镜像磁盘空间使用和容器启动时间性能,并与UnionFS配合使用。覆盖文件系统覆盖文件系统位于现有文件系统之上,将上层目录树和下层目录树组合在一起,并将它们呈现为一个目录。这些目录称为图层。下层保持不变。每一层只增加与下一层的差异(计算机术语中的“diff”),这个统一过程称为联合挂载。最低的目录或镜像层称为lowerdir,上面的目录称为upperdir。最终的叠加层或统一层称为合并层。分层文件系统的常用术语包括这些层的定义:基础层:这是文件系统文件所在的位置。就容器镜像而言,这一层是您的基础镜像。覆盖层:通常被称为容器层,因为对正在运行的容器所做的所有更改,例如添加、删除或修改文件,都会写入此可写层。对该层所做的所有修改都存储在下一层中,这是基础层和差异层的联合视图。差异层Diff层包含在叠加层中所做的所有修改。如果您编写的内容已经在基础层中,覆盖文件系统会将文件复制到diff层并进行您想要编写的更改。这称为写时复制。Snapper由层和图的使用驱动,容器可以构建、管理和分发它们的更改作为容器文件系统的一部分。但是用Graph来驱动Graphdriver的工作确实很复杂,而且容易出错。SnapShotter与图形驱动程序的不同之处在于它们不需要了解图像或容器。Snappers的工作方式与Git非常相似,例如具有树的概念并在每次提交时跟踪对树的更改。快照快照表示文件系统状态。快照具有父子关系,使用一组目录。可以在父级与其快照之间进行差异比较(diff)以创建层。Snapper提供了一个API,用于分配、快照和安装抽象的分层文件系统。总结您现在对什么是容器镜像以及它们的分层方法如何使容器具有可移植性有了很好的理解。下面介绍一下容器的运行机制和内部结构。
