摘要:包含的內容一個由可選和四部分組成。對于這兩種不同類型的文件格式,標準定義了兩個新的,分別是和。最新的標準里面并沒有涉及到,不過估計后續會加上。
上一篇介紹了hello-world的大概流程,那么hello-world的image里面到底包含了些什么呢?里面的格式是怎么樣的呢?
image所包含的內容以及格式都是有標準的,由Open Containers Initiative(OCI)負責維護,地址為image-spec,本文將對該標準做一個簡單的解釋。
image包含的內容一個image由manifest、image index (可選)、filesystem layers和configuration四部分組成。
關系圖先來看看構成image的四部分的關系圖:
+-----------------------+ | Image Index(optional) | +-----------------------+ | | 1..* ↓ +----------------------+ | Image Manifest | +----------------------+ | 1..1 | 1..* +---------------+--------------+ | | ↓ ↓ +--------------+ +-------------------+ | Image Config | | Filesystem Layers | +--------------+ +-------------------+
Image Index和Manifest的關系是"1..*",表示它們是一對多的關系
Image Manifest和Config的關系是"1..1",表示它們是一對一的關系
Image Manifest和Filesystem Layers是一對多的關系
下面分別介紹它們各自都包含了哪些內容。
Filesystem LayersFilesystem Layer包含了文件系統的信息,即該image包含了哪些文件/目錄,以及它們的屬性和數據。
包含的內容每個filesystem layer都包含了在上一個layer上的改動情況,主要包含三方面的內容:
變化類型:是增加、修改還是刪除了文件
文件類型:每個變化發生在哪種文件類型上
文件屬性:文件的修改時間、用戶ID、組ID、RWX權限等
比如在某一層增加了一個文件,那么這一層所包含的內容就是增加的這個文件的數據以及它的屬性,具體的細節請參考標準文檔。
打包格式最終每個layer都會打包成一個文件,這個文件的格式可以是tar和tar+gzip兩種中的一種。
對于這兩種不同類型的文件格式,標準定義了兩個新的media types,分別是application/vnd.oci.image.layer.v1.tar和application/vnd.oci.image.layer.v1.tar+gzip。
同時標準還定義了application/vnd.oci.image.layer.nondistributable.v1.tar和application/vnd.oci.image.layer.nondistributable.v1.tar+gzip這兩種對應于nondistributable的格式,其實這兩種格式和前兩種格式包含的內容是一樣的,只是用不同的類型名稱來區分它們的用途,對于名稱中有nondistributable的layer,標準要求這種類型的layer不能上傳,只能下載。
Image Config做過web開發的程序員對media type應該比較熟悉,簡單點說,就是當客戶端用http協議下載一個文件的時候,需要在http的首部帶上Accept字段,告訴服務器端它支持哪些類型的文件,服務器返回文件的時候,需要在http的首部帶上Content-Type字段,告訴客戶端返回文件的類型,如Accept: text/html,application/xml和Content-Type: text/html。
image config就是一個json文件,它的media type是application/vnd.oci.image.config.v1+json,這個json文件包含了對這個image的描述。先看看官方網站給的例子:
{ "created": "2015-10-31T22:22:56.015925234Z", "author": "Alyssa P. Hacker", "architecture": "amd64", "os": "linux", "config": { "User": "alice", "ExposedPorts": { "8080/tcp": {} }, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "FOO=oci_is_a", "BAR=well_written_spec" ], "Entrypoint": [ "/bin/my-app-binary" ], "Cmd": [ "--foreground", "--config", "/etc/my-app.d/default.cfg" ], "Volumes": { "/var/job-result-data": {}, "/var/log/my-app-logs": {} }, "WorkingDir": "/home/alice", "Labels": { "com.example.project.git.url": "https://example.com/project.git", "com.example.project.git.commit": "45a939b2999782a3f005621a8d0f29aa387e1d6b" } }, "rootfs": { "diff_ids": [ "sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1", "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" ], "type": "layers" }, "history": [ { "created": "2015-10-31T22:22:54.690851953Z", "created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /" }, { "created": "2015-10-31T22:22:55.613815829Z", "created_by": "/bin/sh -c #(nop) CMD ["sh"]", "empty_layer": true } ] }
這里只介紹幾個比較重要的屬性,其它的請參考標準文檔
architecture:CPU架構類型,現在大部分都是amd64,不過arm64估計會慢慢多起來
os:操作系統,本人只用過linux
config:當根據這個image啟動container時,config里面的配置就是運行container時的默認參數,在后續介紹runtime的時候再仔細介紹每一項的意義
rootfs:指定了image所包含的filesystem layers,type的值必須是layers,diff_ids包含了layer的列表(順序排列),每一個sha256就是每層layer對應tar包的sha256碼
manifestmanifest也是一個json文件,media type為application/vnd.oci.image.manifest.v1+json,這個文件包含了對前面filesystem layers和image config的描述,一看官方網站給出的示例就明白了:
manifest文件中config的sha256就是image的ID,即上面image config文件的sha256值,這里是b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7
{ "schemaVersion": 2, "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "size": 7023, "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7" }, "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "size": 32654, "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f" }, { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "size": 16724, "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b" }, { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "size": 73109, "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736" } ], "annotations": { "com.example.key1": "value1", "com.example.key2": "value2" } }
config里面包含了對image config文件的描述,有media type,文件大小,以及sha256碼
layers包含了對每一個layer的描述,和對config文件的描述一樣,也包含了media type,文件大小,以及sha256碼
Image Index(可選)這里layer的sha256和image config文件中的diff_ids有可能不一樣,比如這里的layer文件格式是tar+gzip,那么這里的sha256就是tar+gzip包的sha256碼,而diff_ids是tar+gzip解壓后tar文件的sha256碼
image index也是個json文件,media type是application/vnd.oci.image.index.v1+json。
其實到manifest為止,已經有了整個image的完整描述,為什么還需要image index這個文件呢?主要原因是manifest描述的image只能支持一個平臺,也沒法支持多個tag,加上index文件的目的就是讓這個image能支持多個平臺和多tag。
image index是v1.0.0-rc5才加進來的一個文件,還不穩定,后面可能還會修改,并且docker現在也不支持該文件,這里看看官方給的示例,先了解一下:
{ "schemaVersion": 2, "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 7143, "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f", "platform": { "architecture": "ppc64le", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 7682, "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270", "platform": { "architecture": "amd64", "os": "linux", "os.features": [ "sse4" ] } } ], "annotations": { "com.example.key1": "value1", "com.example.key2": "value2" } }
index文件包含了對image中所有manifest的描述,相當于一個manifest列表,包括每個manifest的media type,文件大小,sha256碼,支持的平臺以及平臺特殊的配置。
比如ubuntu想讓它的image支持amd64和arm64平臺,于是它在兩個平臺上都編譯好相應的包,然后將兩個平臺的layer都放到這個image的filesystem layers里面,然后寫兩個config文件和兩個manifest文件,再加上這樣一個描述不同平臺manifest的index文件,就可以讓這個image支持兩個平臺了,兩個平臺的用戶可以使用同樣的命令得到自己平臺想要的那些layer。
image layoutimage index最新的標準里面并沒有涉及到tag,不過估計后續會加上。
上面介紹了image所包含的內容,在開始介紹layout之前,先來回顧一下上一篇介紹hello-world時提到的從register服務器拉image的過程:
首先獲取image的manifests
根據manifests文件中config的sha256碼,得到image config文件
遍歷manifests里面的所有layer,根據其sha256碼在本地找,如果找到對應的layer,則跳過,否則從服務器取相應layer的壓縮包
等上面的所有步驟完成后,就會拼出完整的image
從上面的過程中可以看出,我們從服務器上取image的時候不需要知道image manifests和config文件的名字,也不需要知道layer壓縮包的名字。
那么image從服務器拉下來后,在本地應該怎么存儲呢?文件名稱和目錄結構應該是怎樣的呢?OCI也有相應的標準,名字叫image layout,有了這樣的標準之后,我們就可以將整個image打成一個包,方便的在不同機器,不同容器平臺之間導入導出。
不過遺憾的是,OCI的這個標準還在變化中,根據github上所看到的,v1.0.0-rc5在v1.0.0-rc4上就有較大的修改,并且現在docker也不支持該標準。
docker對OCI image layout的支持還在開發中,相關動態請關注:Support OCI image layout in docker save/load
這里我們看看v1.0.0-rc4的格式,下面是hello-world image的目錄結構,了解一下:
dev@debian:~/images/hello-world$ tree . ├── blobs │?? └── sha256 │?? ├── 636fcf0bc8246e08d2df4771dc764d35ea50428b8dfaa904773b0707cb4f6303 │?? ├── 7520415ce76232cdd62ecc345cea5ea44f5b6b144dc62351f2cd2b08382532a3 │?? └── 9b8e3ce88f3a2aaa478cfe613632f38d27be5eddaa002a719fa1bfa9ff4f7f63 ├── oci-layout └── refs └── latestoci-layout
包含image標準的版本信息
dev@debian:~/images/hello-world$ cat ./oci-layout| jq . { "imageLayoutVersion": "1.0.0" }refs
里面的每個文件就是一個tag(hello-world的image中只有一個latest tag),每個tag都是一個多帶帶的image,相當于一個image的layout包里面可以包含多個有關系的image,文件的內容如下:
dev@debian:~/images/hello-world$ cat ./refs/latest | jq . { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:9b8e3ce88f3a2aaa478cfe613632f38d27be5eddaa002a719fa1bfa9ff4f7f63", "size": 347 }
其實就是對manifest文件的描述,根據sha256就可以在blobs的目錄里面找到相應的manifest文件
blobs里面包含了具體文件的內容,每個文件名都是其內容的sha256碼,根據上面refs文件里面的sha256,就能在這里找到對應的manifest文件的內容,然后根據manifest文件的內容,就能一步一步的往下找到image config文件和filesystem layers文件。
dev@debian:~/images/hello-world$ file ./blobs/sha256/* ./blobs/sha256/636fcf0bc8246e08d2df4771dc764d35ea50428b8dfaa904773b0707cb4f6303: ASCII text, with very long lines, with no line terminators ./blobs/sha256/7520415ce76232cdd62ecc345cea5ea44f5b6b144dc62351f2cd2b08382532a3: gzip compressed data ./blobs/sha256/9b8e3ce88f3a2aaa478cfe613632f38d27be5eddaa002a719fa1bfa9ff4f7f63: ASCII text, with very long lines, with no line terminators dev@debian:~/images/hello-world$ sha256sum ./blobs/sha256/* 636fcf0bc8246e08d2df4771dc764d35ea50428b8dfaa904773b0707cb4f6303 ./blobs/sha256/636fcf0bc8246e08d2df4771dc764d35ea50428b8dfaa904773b0707cb4f6303 7520415ce76232cdd62ecc345cea5ea44f5b6b144dc62351f2cd2b08382532a3 ./blobs/sha256/7520415ce76232cdd62ecc345cea5ea44f5b6b144dc62351f2cd2b08382532a3 9b8e3ce88f3a2aaa478cfe613632f38d27be5eddaa002a719fa1bfa9ff4f7f63 ./blobs/sha256/9b8e3ce88f3a2aaa478cfe613632f38d27be5eddaa002a719fa1bfa9ff4f7f63下載image
上面介紹image layout時用到了hello-world的image,它是從哪里來的呢?
為了快速的構建container的rootfs,docker在本地有它自己的一套image管理方式,有自己的layout,并且目前docker save命令也不支持導出OCI格式的image,只能導出docker自己的格式,所以我們只能借助其它的工具得到OCI格式的image。
這里我們用skopeo來演示一下從docker hub上拉取hello-world的image,并把它在本地存成OCI的layout。
這里生成的layout和最新版本的標準有點差別,和v1.0.0-rc4的標準一致,如果你用同樣的命令得到不一樣的layout,說明skopeo有更新,支持了更新的標準。
#這里的所有命令在debian 8.6的環節上運行通過 #編譯安裝skopeo $ git clone https://github.com/projectatomic/skopeo $GOPATH/src/github.com/projectatomic/skopeo $ sudo apt-get install libgpgme11-dev libdevmapper-dev btrfs-tools go-md2man $ cd $GOPATH/src/github.com/projectatomic/skopeo $ make binary-local $ sudo make install #下載hello-world的image $ skopeo copy docker://hello-world oci:hello-world $ tree hello-world/ hello-world/ ├── blobs │?? └── sha256 │?? ├── 636fcf0bc8246e08d2df4771dc764d35ea50428b8dfaa904773b0707cb4f6303 │?? ├── 7520415ce76232cdd62ecc345cea5ea44f5b6b144dc62351f2cd2b08382532a3 │?? └── 9b8e3ce88f3a2aaa478cfe613632f38d27be5eddaa002a719fa1bfa9ff4f7f63 ├── oci-layout └── refs └── latest結束語
雖然OCI iamge的標準還處于rc階段,沒有正式release,并且docker現在也不支持OCI image的layout,不過相信過不了多久,OCI image的標準就會被廣泛支持,先了解一下還是很有必要的。
參考OCI Image Format Specification
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/26899.html
摘要:包含的內容本系列主要介紹三個上的項目由于只介紹核心的東西,所以不會包含下面這些項目使用語言開發,將多個相關的容器配置在一起,從而可以同時創建啟動停止和監控它們。由于本人時間安排發生變化,本系列停止更新,后面不確定是否會繼續,非常抱歉。 本人docker初學者,邊學習邊總結,一方面加深自己的理解,另一方面希望對其他想深入了解docker的同學有所幫助。 由于本人缺乏實戰經驗,錯誤在所難免...
摘要:里面可以通過等方式得到一個,得到之后在本地是怎么存儲的呢本篇將以為例,簡述的獲取和存儲方式。鏡像相關的配置里面和有關的目錄為,里面存放著的所有信息,可以通過下面這個的啟動參數來修改這個目錄的路徑。 docker里面可以通過docker pull、docker build、docker commit、docker load、docker import等方式得到一個image,得到imag...
摘要:進程啟動后,就會按照的標準準備好相關運行時環境,然后啟動進程。涉及到標準輸入輸出重定向,這里不細說這里是它們之間的交互流程流程對應的文字描述如下客戶端發送創建容器請求給,收到請求后,發現本地沒有相應的額,于是返回失敗。 在程序員的世界里,hello world是個很特殊的存在,當我們接觸一門新的語言、新的開發庫或者框架時,第一時間想了解的一般都是怎么實現一個hello world,然后...
摘要:相關工具本文將用到三個工具,分別是和。根據生成的的就是運行容器時需要的東西的集合。使用運行該有了后,就可以用來運行該容器了這里直接用的代替命令,如果你自己編譯了的,那么用命令也是一樣的。 上一篇介紹了image的格式,這里我們就來用一下hello-world這個image,看怎么輸出和docker run hello-world同樣的內容。 相關工具 本文將用到三個工具,分別是skop...
閱讀 1873·2021-11-25 09:43
閱讀 2151·2021-11-19 09:40
閱讀 3432·2021-11-18 13:12
閱讀 1744·2021-09-29 09:35
閱讀 666·2021-08-24 10:00
閱讀 2512·2019-08-30 15:55
閱讀 1718·2019-08-30 12:56
閱讀 1820·2019-08-28 17:59