在云原生应用的开发中,应用会被打包成容器镜像。容器镜像遵循 OCI 镜像规范。了解 OCI 镜像规范,对构建容器镜像有重要的作用。
在介绍 OCI 镜像规范之前,首先需要介绍内容可寻址的文件系统。
内容可寻址的文件系统
我们通常使用的文件系统是根据路径来查找文件的,比如 /etc/nginx/nginx.conf
指向的就是文件系统上的一个文件。这种寻址方式很容易理解,使用起来也简单。其中的问题在于,对于同一个路径,它所指向的文件的内容是可变的。在不同的时间点上访问同一个路径的文件,它所包含的内容会产生变化。
容器镜像的一个重要优势是不可变。为了满足这种需求,容器镜像使用的是内容可寻址的方式。基本的思路是对每一个文件,使用摘要算法得到该文件的摘要。使用该摘要作为该文件的寻址方式。SHA-256 和 SHA-512 是常用的摘要算法。
当文件的内容发生变化时,它的摘要也会发生变化。使用同一个摘要,总是可以找到同样的内容。在这种寻址方式下,可以把文件系统看成是一个巨大的哈希表。哈希表的键是摘要,而对应的值则是文件的内容。
工具支持
在开始之前,需要安装 skopeo 和 jq 两个工具。以 Ubuntu 为例,下面给出了相关的安装命令:
sudo apt-get update
sudo apt-get -y install skopeo
sudo apt-get -y install jq
复制镜像
作为示例的是 Nginx 的镜像。首先使用 skopeo copy
命令把 Nginx 镜像转换成 OCI 镜像的格式。skopeo copy
的源 docker://nginx
表示 Docker Hub 上的标签为 latest
的 Nginx 镜像,目标 oci:local_nginx
的前缀 oci:
表示 OCI 镜像格式,local_nginx
是本地目录的名称。
skopeo copy docker://nginx oci:local_nginx
下面是该命令的输出结果。
Getting image source signatures
Copying blob eff15d958d66 done
Copying blob 1e5351450a59 done
Copying blob 2df63e6ce2be done
Copying blob 9171c7ae368c done
Copying blob 020f975acd28 done
Copying blob 266f639b35ad done
Copying config 9d446b871e done
Writing manifest to image destination
Storing signatures
该命令运行完成之后,Nginx 镜像的内容就以 OCI 镜像规范的格式保存到了本地。
镜像的内容
转到 local_nginx
目录,使用 tree
命令查看该目录的内容。
tree --du .
在该目录中,根目录下有两个文件 oci-layout
和 index.json
。目录 blobs
中包含了文件的实际内容,使用的是内容寻址的方式。目录名称 sha256
表示内容摘要的算法,对应于 SHA-256。文件名是摘要。
.
├── [ 56737397] blobs
│ └── [ 56733301] sha256
│ ├── [ 668] 020f975acd28936c7ff43827238aed4771d14235dc983389ec149811f7e0b7cf
│ ├── [ 25347687] 1e5351450a593c3a3d7a5104f93c8b80d8dc00c827158cb3a5bf985916ea3f75
│ ├── [ 1394] 266f639b35ad602ee76c3b4d4cf88285a50adf8f561d8d96d331db732fe16982
│ ├── [ 602] 2df63e6ce2be0b3cefd3e659558e92b8085f032db96828343ec9cf0b7d4409fe
│ ├── [ 895] 9171c7ae368c6ca24dae913fce356801f624f656360c78ca956a92c3f0fe0ec7
│ ├── [ 6566] 9d446b871e5882110acf8dc0ab827425b8d25184f9426b12b2073186a0b2cdce
│ ├── [ 1126] b77780a5c0973c290799dea52ccbc975f61954907de8108d6f99e65a44fa7623
│ └── [ 31370267] eff15d958d664f0874d16aee393cc44387031ee0a68ef8542d0056c747f378e8
├── [ 187] index.json
└── [ 31] oci-layout
56741711 bytes used in 2 directories, 10 files
oci-layout
是 OCI 镜像规范的占位符,其中的内容如下所示。
{"image