
1.5 镜像管理和分发
镜像管理和分发是容器应用的基础功能,包括本地镜像管理、镜像仓库的镜像分发及客户端和镜像仓库之间的接口等。因为Docker是目前使用相当普遍且功能较完整的容器管理软件,所以本节先介绍Docker镜像的分发机制,再以此为基础,说明OCI的分发规范。
1.5.1 Docker镜像管理和分发
Docker实现了较完善的镜像管理分发流程,其中镜像管理包括三个主要功能:镜像推送、镜像拉取和镜像删除,包括本地镜像管理和远端镜像仓库的交互,具体作用如表1-3所示。
表1-3

Docker命令行工具提供了丰富的本地镜像管理功能,包括镜像构建、查询、删除等。还提供了涉及远端镜像仓库的操作(拉取和推送等),这些都可以通过Docker Daemon调用Docker Registry的API来实现。
Docker镜像的分发主要通过Docker Registry、Docker客户端、Docker Daemon等软件协作来完成。如图1-16所示,Docker Daemon监听客户端的请求,管理本地镜像、容器、网络和存储卷等资源;Docker客户端是大多数用户与Docker系统交互的工具,用户执行“docker pull”命令,可从配置的仓库服务中拉取镜像;用户执行“docker push”命令,可将镜像从本地推送到镜像仓库服务中。Docker Registry服务是存储镜像的仓库,Docker默认使用的公网服务是Docker Hub,也可以使用Docker Distribution等软件在本地提供镜像仓库服务。

图1-16
Docker Distribution是第一个实现了打包、发布、存储和镜像发放的工具,起到Docker Registry的作用。Docker Distribution提供了若干种存储驱动的支持,主要包括内存、本地文件系统、亚马逊S3、微软Azure块存储、OpenStack Swift、阿里云的OSS和谷歌的云存储等。镜像仓库存储模块定义了标准的编程接口,用户可按需实现新的存储驱动。此外,Docker Distribution 在镜像功能的基础上提供了完整的认证和授权流程,具体细节可参考第5章。
Docker Distribution镜像仓库为了方便用户使用,提供了可运行的官方镜像来启动服务。用户可通过http://127.0.0.1:5000 访问镜像仓库服务:

Docker Distribution的2.0版本是Docker Registry HTTP API V2规范的一个实现,提供了镜像推送和拉取、简易的部署、插件化的后端存储及 Webhook 通知机制等功能。1.5.2节介绍的OCI分发规范是基于Docker Registry HTTP API V2规范来制定的,因此也可认为Docker Distribution实现了大部分OCI分发规范,二者在很大程度上是兼容的。
Harbor采用了Docker Distribution作为后端镜像存储,在Harbor 2.0之前的版本中,镜像相关的功能大部分交由Docker Distribution处理;从Harbor 2.0版本开始,镜像等OCI制品的元数据由Harbor自己维护,Docker Distribution仅作为镜像等OCI制品的存储库。
1.5.2 OCI分发规范
OCI还有一个正在制定的分发规范(Distribution Specification),这个规范在OCI镜像规范的基础上定义了客户端和镜像仓库之间镜像操作的交互接口。OCI的指导思想是先有工业界的实践,再将实践总结成技术规范,因此尽管分发规范还没有正式发布,但以Docker Distribution为基础的镜像仓库已经在很多实际环境下使用,Docker Distribution所使用的Docker Registry HTTP API V2也成为事实上的标准。
OCI分发规范是基于Docker Registry HTTP API V2的标准化容器镜像分发过程制定的。OCI分发规范定义了仓库服务和仓库客户端交互的协议,主要包括:面向命名空间(Namespace)的URI格式、能够拉取和推送v2格式清单的仓库服务、支持可续传的推送过程及v2客户端的要求等。
OCI分发规范主要以API接口描述为主,在表1-4中列出了几个主要接口。
表1-4

续表

1.5.3 OCI Artifact
从1.4.5节图1-13可以看到,OCI镜像规范的结构特点是由一个(可选的)镜像索引来指向多个清单,每个清单都指向一个配置和若干个层文件(Layer)。如果镜像没有包括镜像索引,则可以仅包含一个清单,且清单指向一个配置和若干个层文件。无论是否有镜像索引,在镜像结构定义中都没有涉及层文件所包含的内容,也就是说,不同用途的数据如Helm Chart、CNAB等制品,可依照OCI镜像规范定义的结构(清单、索引等)把内容打包到层文件里面,从而成为符合OCI规范的“镜像”,既可以推送到支持OCI分发规范的Registry里,也可以像拉取镜像那样从Registry中下载。
为了和OCI镜像做区分,这种遵循OCI清单和索引的定义,能够通过OCI分发规范推送和拉取的内容,可以统称为OCI Artifact(OCI制品),简称Artifact(制品)。在OCI分发规范中,还可以给Artifact的清单或者索引标注若干个Tag来附加版本等信息,以方便后续的访问和使用,如图1-17所示。如果Artifact没有包含索引,则Tag可以被标注在清单上;如果Artifact使用了索引,则Tag可以被标注在索引上,而清单上的Tag则是可选的。一个Artifact如果没有被标注Tag,则只能通过清单或索引的摘要来访问。从组成结构来看,OCI镜像只是OCI Artifact的一个“特例”,读者可以通过比较图1-17和图1-13来理解。

图1-17
把各类数据封装成OCI Artifact的好处之一,是可以借助已有的支持OCI分发规范的镜像仓库服务(如Harbor 2.0等)来实现不同类型数据的存储、权限、复制和分发等能力,而无须针对每种特定类型的数据设立或开发不同的仓库服务,使开发者能专注于新类型的Artifact的创新。
开发者如果希望自定义一种新的Artifact类型,就可以按照OCI的制品作者指导文档(Artifact Author Guidance)来定义配置、清单、索引等结构,可分4个步骤来完成。
(1)定义OCI Artifact的类型。Artifact的类型主要是为了Artifact的工具(如Docker客户端)能够获知Artifact的类型,从而确定能否处理该Artifact。这有点像文件的扩展名(如.pdf、.jpg等),可以让操作系统识别出文件的类型,从而启动相应的应用程序来处理该文件。Artifact的类型由清单中的config.mediaType属性定义,因此Artifact的工具通常从清单开始分析Artifact的类型,以决定后续的处理流程。
(2)确保Artifact类型的唯一性。既然Artifact的类型很重要,开发者就需要确保所创建的Artifact类型是唯一的,和其他Artifact类型都不能重名。OCI的指导文档给出了类型必须符合的格式:

格式中各个字段的含义如表1-5所示。
表1-5

一些常见的OCI Artifact配置类型如表1-6所示。
表1-6

(3)Artifact 的内容由一组层文件和一个可选的配置文件组成。每个层文件都可以是单个文件、一组文件或者tar格式的文件,能够以Blob的形式存放在registry的存储中。
开发者可以根据Artifact的需要确定每个层文件的内容格式,如.json、.xml、.tar等,然后在清单的layer.mediaType属性中说明内容类型。内容类型可以沿用IANA通用格式,如application/json和application/xml等。如果需要自定义类型,则可以采用如下格式:

格式中各个字段的含义如表1-7所示。
表1-7

续表

一些常见的OCI Artifact层文件类型如表1-8所示。
表1-8

(4)开发者在IANA中注册Artifact的config.mediaType和layer.mediaType的类型,确保类型的唯一性和拥有者,同时可以让其他用户使用这些类型。
经过上述步骤,开发者自定义的Artifact类型就完成了,配上适当的客户端软件对数据打包、推送和拉取,即可与符合OCI分发规范的仓库服务交互。
因为OCI Artifact带来了管理和运维上的便利,所以开发者已经创建了多种OCI Artifact,常见的OCI Artifact包括Helm Chart、CNAB、Singularity等。为适应云原生用户者的需求,Harbor 2.0的架构做了比较大的调整和改进,以便用户在Harbor中存取和管理符合OCI规范的Artifact。Harbor中管理容器镜像的各种功能,在适用的情况下,都可以扩展到OCI Artifact上,如访问权限控制、推送和拉取、界面查询、远程复制等,这大大方便了用户对云原生Artifact的管理和使用。