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