摘要:里面可以通過等方式得到一個,得到之后在本地是怎么存儲的呢本篇將以為例,簡述的獲取和存儲方式。鏡像相關的配置里面和有關的目錄為,里面存放著的所有信息,可以通過下面這個的啟動參數(shù)來修改這個目錄的路徑。
docker里面可以通過docker pull、docker build、docker commit、docker load、docker import等方式得到一個image,得到image之后docker在本地是怎么存儲的呢?本篇將以git pull為例,簡述image的獲取和存儲方式。
鏡像相關的配置docker里面和image有關的目錄為/var/lib/docker,里面存放著image的所有信息,可以通過下面這個dockerd的啟動參數(shù)來修改這個目錄的路徑。
--graph, -g /var/lib/docker Root of the Docker runtime鏡像的引用方式
在需要引用image的時候,比如docker pull的時候,或者運行容器的時候,都需要指定一個image名稱,引用一個鏡像有多種方式,下面以ubuntu為例進行說明.
docker hub上的官方鏡像由于sha256碼太長,所以用bcdef...來表示完整的sha256,節(jié)約空間
ubuntu: 官方提供的最新ubuntu鏡像,對應的完整名稱為docker.io/library/ubuntu:latest
ubuntu:16.04: 官方提供的ubuntu 16.04鏡像,對應的完整名稱為docker.io/library/ubuntu:16.04
ubuntu:@sha256:abcdef...: 官方提供的digest碼為sha256:abcdef...的ubuntu鏡像,對應的完整名稱為docker.io/library/ubuntu@sha256:abcdef...
docker hub上的非官方(個人)鏡像引用方式和官方鏡像一樣,唯一不同的是需要在鏡像名稱前面帶上用戶前綴,如:
user1/ubuntu: 由user1提供的最新ubuntu鏡像, 對應的完整名稱為docker.io/user1/ubuntu:latest
user1/ubuntu:16.04 和 user1/ubuntu:@sha256:abcdef...這兩種方式也是和上面一樣,等同于docker.io/user1/ubuntu:16.04和docker.io/user1/ubuntu:@sha256:abcdef...
自己搭建的registry里的鏡像引用方式和docker hub一樣,唯一不同的是需要在鏡像名稱最前面帶上地址,如:
localhost:5000/ubuntu: 本地自己搭建的registry(localhost:5000)里面的官方ubuntu的最新鏡像,對應的完整名稱為localhost:5000/library/ubuntu:latest
localhost:5000/user1/ubuntu@sha256:a123def...: 本地自己搭建的registry(localhost:5000)里面由用戶user1提供的digest為sha256:a123def的ubuntu鏡像
其它的幾種情況和上面的類似。
為什么需要鏡像的digest?對于某些image來說,可能在發(fā)布之后還會做一些更新,比如安全方面的,這時雖然鏡像的內容變了,但鏡像的名稱和tag沒有變,所以會造成前后兩次通過同樣的名稱和tag從服務器得到不同的兩個鏡像的問題,于是docker引入了鏡像的digest的概念,一個鏡像的digest就是鏡像的manifes文件的sha256碼,當鏡像的內容發(fā)生變化的時候,即鏡像的layer發(fā)生變化,從而layer的sha256發(fā)生變化,而manifest里面包含了每一個layer的sha256,所以manifest的sha256也會發(fā)生變化,即鏡像的digest發(fā)生變化,這樣就保證了digest能唯一的對應一個鏡像。
docker pull的大概過程如果對Image manifest,Image Config和Filesystem Layers等概念不是很了解,請先參考image(鏡像)是什么。
取image的大概過程如下:
docker發(fā)送image的名稱+tag(或者digest)給registry服務器,服務器根據(jù)收到的image的名稱+tag(或者digest),找到相應image的manifest,然后將manifest返回給docker
docker得到manifest后,讀取里面image配置文件的digest(sha256),這個sha256碼就是image的ID
根據(jù)ID在本地找有沒有存在同樣ID的image,有的話就不用繼續(xù)下載了
如果沒有,那么會給registry服務器發(fā)請求(里面包含配置文件的sha256和media type),拿到image的配置文件(Image Config)
根據(jù)配置文件中的diff_ids(每個diffid對應一個layer tar包的sha256,tar包相當于layer的原始格式),在本地找對應的layer是否存在
如果layer不存在,則根據(jù)manifest里面layer的sha256和media type去服務器拿相應的layer(相當去拿壓縮格式的包)。
拿到后進行解壓,并檢查解壓后tar包的sha256能否和配置文件(Image Config)中的diff_id對的上,對不上說明有問題,下載失敗
根據(jù)docker所用的后臺文件系統(tǒng)類型,解壓tar包并放到指定的目錄
等所有的layer都下載完成后,整個image下載完成,就可以使用了
注意: 對于layer來說,config文件中diffid是layer的tar包的sha256,而manifest文件中的digest依賴于media type,比如media type是tar+gzip,那digest就是layer的tar包經過gzip壓縮后的內容的sha256,如果media type就是tar的話,diffid和digest就會一樣。
image本地存放位置dockerd和registry服務器之間的協(xié)議為Registry HTTP API V2。
這里以ubuntu的image為例,展示docker的image存儲方式。
先看看debian的image id和digest,然后再分析image數(shù)據(jù)都存在哪里
dev@debian:~$ docker images --digests REPOSITORY TAG DIGEST MAGE ID CREATED SIZE ubuntu latest sha256:ea1d85... 7b9b13f7b9c0 4 weeks ago 118 MB ......
repositories.json對于本地生成的鏡像來說,由于沒有上傳到registry上去,所以沒有digest,因為鏡像的manifest由registry生成
repositories.json中記錄了和本地image相關的repository信息,主要是name和image id的對應關系,當image從registry上被pull下來后,就會更新該文件:
#這里目錄中的aufs為docker后臺所采用的存儲文件系統(tǒng)名稱, #如果是其他的文件系統(tǒng)的話,名字會是其他的,比如btrfs、overlay2、devicemapper等。 root@debian:~# cat /var/lib/docker/image/aufs/repositories.json|python -m json.tool { "Repositories": { "ubuntu": { "ubuntu:latest": "sha256:7b9b13f7b9c086adfb6be4d2d264f90f16b4d1d5b3ab9f955caa728c3675c8a2", "ubuntu@sha256:ea1d854d38be82f54d39efe2c67000bed1b03348bcc2f3dc094f260855dff368": "sha256:7b9b13f7b9c086adfb6be4d2d264f90f16b4d1d5b3ab9f955caa728c3675c8a2" } ...... } }
ubuntu: repository的名稱,前面沒有服務器信息的表示這是官方registry(docker hub)里面的repository,里面包含的都是image標識和image ID的對應關系
ubuntu:latest和debian@sha256:ea1d85...: 他們都指向同一個image(sha256:7b9b13...)
配置文件(image config)docker根據(jù)第一步得到的manifest,從registry拿到config文件,然后保存在image/aufs/imagedb/content/sha256/目錄下,文件名稱就是文件內容的sha256碼,即image id:
root@debian:~# sha256sum /var/lib/docker/image/aufs/imagedb/content/sha256/7b9b13f7b9c086adfb6be4d2d264f90f16b4d1d5b3ab9f955caa728c3675c8a2 7b9b13f7b9c086adfb6be4d2d264f90f16b4d1d5b3ab9f955caa728c3675c8a2 /var/lib/docker/image/aufs/imagedb/content/sha256/7b9b13f7b9c086adfb6be4d2d264f90f16b4d1d5b3ab9f955caa728c3675c8a2 #這里我們只關注這個image的rootfs, #從diff_ids里可以看出ubuntu:latest這個image包含了5個layer, #從上到下依次是從底層到頂層,6a8bf8...是最底層,d8b353...是最頂層 root@debian:~# cat /var/lib/docker/image/aufs/imagedb/content/sha256/7b9b13f7b9c086adfb6be4d2d264f90f16b4d1d5b3ab9f955caa728c3675c8a2|python -m json.tool ...... "rootfs": { "diff_ids": [ "sha256:6a8bf8c8edbd705f67cdc062eee3911470a38a763258c81c05da1f28d6eec896", "sha256:fe9a3f9c4559684b75bba751883fa084d34e418c018d687ddc25c3f23f13f657", "sha256:fc9e1e5e38f700997585295bd65a47e58f3da7b2f0e6a971e14a6104f199de1f", "sha256:f2e85bc0b7b17ab33f9060d2f24824defe600e189b05a895d60b2e8a6a7bd0d7", "sha256:d8b353eb3025c49e029567b2a01e517f7f7d32537ee47e64a7eac19fa68a33f3" ], "type": "layers" } ......layer的diff_id和digest的對應關系
layer的diff_id存在image的配置文件中,而layer的digest存在image的manifest中,他們的對應關系被存儲在了image/aufs/distribution目錄下:
root@debian:~# tree -d /var/lib/docker/image/aufs/distribution/ /var/lib/docker/image/aufs/distribution/ ├── diffid-by-digest │?? └── sha256 └── v2metadata-by-diffid └── sha256
diffid-by-digest: 存放digest到diffid的對應關系
v2metadata-by-diffid: 存放diffid到digest的對應關系
#這里以最底層layer(6a8bf8...)為例,查看其digest信息 root@debian:~# cat /var/lib/docker/image/aufs/distribution/v2metadata-by-diffid/sha256/6a8bf8c8edbd705f67cdc062eee3911470a38a763258c81c05da1f28d6eec896|python -m json.tool [ { "Digest": "sha256:bd97b43c27e332fc4e00edf827bbc26369ad375187ce6eee91c616ad275884b1", "HMAC": "", "SourceRepository": "docker.io/library/ubuntu" } ] #根據(jù)digest得到diffid root@debian:~# cat /var/lib/docker/image/aufs/distribution/diffid-by-digest/sha256/bd97b43c27e332fc4e00edf827bbc26369ad375187ce6eee91c616ad275884b1 sha256:6a8bf8c8edbd705f67cdc062eee3911470a38a763258c81c05da1f28d6eec896layer的元數(shù)據(jù)
layer的屬性信息都放在了image/aufs/layerdb目錄下,目錄名稱是layer的chainid,由于最底層的layer的chainid和diffid相同,所以這里我們用第二層(fe9a3f...)作為示例:
計算chainid時,用到了所有祖先layer的信息,從而能保證根據(jù)chainid得到的rootfs是唯一的。比如我在debian和ubuntu的image基礎上都添加了一個同樣的文件,那么commit之后新增加的這兩個layer具有相同的內容,相同的diffid,但由于他們的父layer不一樣,所以他們的chainid會不一樣,從而根據(jù)chainid能找到唯一的rootfs。計算chainid的方法請參考image spec
#計算chainid #這里fe9a3f...是第二層的diffid,而6a8bf8...是fe9a3f...父層的chainid, #由于6a8bf8...是最底層,它沒有父層,所以6a8bf8...的chainid就是6a8bf8... dev@debian:~$ echo -n "sha256:6a8bf8c8edbd705f67cdc062eee3911470a38a763258c81c05da1f28d6eec896 sha256:fe9a3f9c4559684b75bba751883fa084d34e418c018d687ddc25c3f23f13f657"|sha256sum - 67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193 - #根據(jù)chainid來看看相應目錄的內容 root@debian:/var/lib/docker/image/aufs/layerdb/sha256/67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193# ls cache-id diff parent size tar-split.json.gz #每個layer都有這樣一個對應的文件夾 #cache-id是docker下載layer的時候在本地生成的一個隨機uuid, #指向真正存放layer文件的地方 root@debian:/var/lib/docker/image/aufs/layerdb/sha256/67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193# cat cache-id b656bf5f0688069cd90ab230c029fdfeb852afcfd0d1733d087474c86a117da3 #diff文件存放layer的diffid root@debian:/var/lib/docker/image/aufs/layerdb/sha256/67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193# cat diff sha256:fe9a3f9c4559684b75bba751883fa084d34e418c018d687ddc25c3f23f13f657 #parent文件存放當前l(fā)ayer的父layer的diffid, #注意:對于最底層的layer來說,由于沒有父layer,所以沒有這個文件 root@debian:/var/lib/docker/image/aufs/layerdb/sha256/67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193# cat parent sha256:6a8bf8c8edbd705f67cdc062eee3911470a38a763258c81c05da1f28d6eec896 #當前l(fā)ayer的大小,單位是字節(jié) root@debian:/var/lib/docker/image/aufs/layerdb/sha256/67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193# cat size 745 #tar-split.json.gz,layer壓縮包的split文件,通過這個文件可以還原layer的tar包, #在docker save導出image的時候會用到 #詳情可參考https://github.com/vbatts/tar-split root@debian:/var/lib/docker/image/aufs/layerdb/sha256/67b5e1df1b671d4751794767b20f6973d77e91528ab475ee1118ce8dab796193# ls -l tar-split.json.gz -rw-r--r-- 1 root root 1429 May 28 22:57 tar-split.json.gzlayer數(shù)據(jù)
docker根據(jù)后臺所采用的文件系統(tǒng)不同,在/var/lib/docker目錄下創(chuàng)建了不同的子目錄,對于debian來說,默認文件系統(tǒng)是aufs,所以所有l(wèi)ayer的文件都放在了/var/lib/docker/aufs目錄下。
root@dev:~# tree -d -L 1 /var/lib/docker/aufs /var/lib/docker/aufs ├── diff ├── layers └── mnt
該目錄下有三個子目錄,layers里面存放的layer的父子關系,diff目錄存放的是每個layer的原始數(shù)據(jù),mnt存儲的是layer和祖先layer疊加起來的數(shù)據(jù)。
注意:由于docker所采用的文件系統(tǒng)不同,/var/lib/docker/
目錄下的目錄結構及組織方式也會不一樣,要具體文件系統(tǒng)具體分析,本文只介紹aufs這種情況。
關于aufs和btrfs的相關特性可以參考Linux文件系統(tǒng)之aufs和Btrfs文件系統(tǒng)之subvolume與snapshot
還是以剛才的第二層layer(fe9a3f...)為例,看看實際的數(shù)據(jù):
#從上面layerdb中,我們已經找到了第二層layer對應的cache id為b656bf... #先看看layers目錄下的這個文件,里面存放的是當前l(fā)ayer的祖先layer的cacheid root@dev:~# cat /var/lib/docker/aufs/layers/b656bf5f0688069cd90ab230c029fdfeb852afcfd0d1733d087474c86a117da3 1e83d2ea184e08eed978127311cc96498e319426abe2fb5004d4b1454598bd76 #再來看看diff目錄下的內容,看這一層包含了哪些文件,從下面的輸出可以看出,這一層包含的文件很少 root@dev:~# tree /var/lib/docker/aufs/diff/b656bf5f0688069cd90ab230c029fdfeb852afcfd0d1733d087474c86a117da3/ /var/lib/docker/aufs/diff/b656bf5f0688069cd90ab230c029fdfeb852afcfd0d1733d087474c86a117da3/ ├── etc │?? ├── apt │?? │?? └── apt.conf.d │?? │?? ├── docker-autoremove-suggests │?? │?? ├── docker-clean │?? │?? ├── docker-gzip-indexes │?? │?? └── docker-no-languages │?? └── dpkg │?? └── dpkg.cfg.d │?? └── docker-apt-speedup ├── sbin │?? └── initctl ├── usr │?? └── sbin │?? └── policy-rc.d └── var └── lib └── dpkg ├── diversions └── diversions-old #再來看看這一層和上一層合并后的文件目錄 root@dev:~# tree /var/lib/docker/aufs/mnt/b656bf5f0688069cd90ab230c029fdfeb852afcfd0d1733d087474c86a117da3/ /var/lib/docker/aufs/mnt/b656bf5f0688069cd90ab230c029fdfeb852afcfd0d1733d087474c86a117da3/ 0 directories, 0 files #為什么是空的呢?這和aufs文件系統(tǒng)有關, #它只有在運行容器的時候,才會將多層合并起來,提供一個統(tǒng)一的視圖, #所以這里看不到這兩層合并之后的效果。manifest文件去哪了?
從前面介紹docker pull的過程中得知,docker是先得到manifest,然后根據(jù)manifest得到config文件和layer。
前面已經介紹了config文件和layer的存儲位置,但唯獨不見manifest,去哪了呢?
manifest里面包含的內容就是對config和layer的sha256 + media type描述,目的就是為了下載config和layer,等image下載完成后,manifest的使命就完成了,里面的信息對于image的本地管理來說沒什么用,所以docker在本地沒有多帶帶的存儲一份manifest文件與之對應。
結束語本篇介紹了image在本地的存儲方式,包括了/var/lib/docker/image和/var/lib/docker/aufs這兩個目錄,但/var/lib/docker/image下面有兩個目錄沒有涉及:
/var/lib/docker/image/aufs/imagedb/metadata:里面存放的是本地image的一些信息,從服務器上pull下來的image不會存數(shù)據(jù)到這個目錄,下次有機會再補充這部分內容。
/var/lib/docker/image/aufs/layerdb/mounts: 創(chuàng)建container時,docker會為每個container在image的基礎上創(chuàng)建一層新的layer,里面主要包含/etc/hosts、/etc/hostname、/etc/resolv.conf等文件,創(chuàng)建的這一層layer信息就放在這里,后續(xù)在介紹容器的時候,會專門介紹這個目錄的內容。
參考docker源代碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/26941.html
摘要:包含的內容本系列主要介紹三個上的項目由于只介紹核心的東西,所以不會包含下面這些項目使用語言開發(fā),將多個相關的容器配置在一起,從而可以同時創(chuàng)建啟動停止和監(jiān)控它們。由于本人時間安排發(fā)生變化,本系列停止更新,后面不確定是否會繼續(xù),非常抱歉。 本人docker初學者,邊學習邊總結,一方面加深自己的理解,另一方面希望對其他想深入了解docker的同學有所幫助。 由于本人缺乏實戰(zhàn)經驗,錯誤在所難免...
摘要:進程啟動后,就會按照的標準準備好相關運行時環(huán)境,然后啟動進程。涉及到標準輸入輸出重定向,這里不細說這里是它們之間的交互流程流程對應的文字描述如下客戶端發(fā)送創(chuàng)建容器請求給,收到請求后,發(fā)現(xiàn)本地沒有相應的額,于是返回失敗。 在程序員的世界里,hello world是個很特殊的存在,當我們接觸一門新的語言、新的開發(fā)庫或者框架時,第一時間想了解的一般都是怎么實現(xiàn)一個hello world,然后...
摘要:包含的內容一個由可選和四部分組成。對于這兩種不同類型的文件格式,標準定義了兩個新的,分別是和。最新的標準里面并沒有涉及到,不過估計后續(xù)會加上。 上一篇介紹了hello-world的大概流程,那么hello-world的image里面到底包含了些什么呢?里面的格式是怎么樣的呢? image所包含的內容以及格式都是有標準的,由Open Containers Initiative(OCI)負...
摘要:結束語命令干的活比較少,主要是準備的和配置文件,配置文件中的項比較多,后續(xù)會挑一些常用的項進行專門介紹。 有了image之后,就可以開始創(chuàng)建并啟動容器了,平時我們都是用docker run命令直接創(chuàng)建并運行一個容器,它的背后其實包含獨立的兩步,一步是docker create創(chuàng)建容器,另一步是docker start啟動容器,本篇將先介紹在docker create這一步中,docke...
閱讀 1436·2021-11-25 09:43
閱讀 2041·2021-07-26 23:38
閱讀 748·2019-08-30 15:53
閱讀 2287·2019-08-30 15:43
閱讀 1176·2019-08-29 18:40
閱讀 1977·2019-08-26 13:28
閱讀 1982·2019-08-23 18:20
閱讀 551·2019-08-23 15:07