1. 鏡像構建
鏡像的構建需要根據oci定義(yi)的規范來進行構建,OCI鏡(jing)像(xiang)規范(image-spec)指定了鏡(jing)像(xiang)需要(yao)按照什么標準來構建,Dockerfile則決定了鏡(jing)(jing)像的(de)layer(鏡(jing)(jing)像層)的(de)內容和相關一(yi)些元(yuan)數據(ju) 簡而言之:
image-spec+DockerFile ====> image
1.1 鏡像構建的過程
構建(jian)鏡像docker build的(de)流程:
-
在Docker Cli 執(zhi)行(xing)鏡(jing)像構建命令并且使(shi)用-f參(can)數來指定(ding)Dockerfile文(wen)件(jian),-t 指定(ding)構建出的鏡(jing)像標簽信息;
-
Docker Cli 會將構(gou)建(jian)命令(ling)后面指定(ding)的路(lu)徑(.)上下文環境(jing)所有(you)文件打(da)包成一個 tar 包,并發送給 Docker 服務端(duan);
-
Docker Deamon 收到客戶端發送的 tar 包并解(jie)壓,根據 Dockerfile 里面的指令進行鏡像的分層構建;
-
Docker 下(xia)載(zai) FROM 語句(ju)中(zhong)指定的基(ji)(ji)礎鏡像,然后將基(ji)(ji)礎鏡像的 layer 聯(lian)合(he)掛載(zai)為一層并在上(shang)面(mian)創(chuang)建一個(ge)空目錄;
-
此時會啟(qi)動一個臨時的容器并在 chroot 中啟(qi)動一個 bash, 運行 RUN 語句中的命(ming)令:RUN : chroot . bin/bash -c "apt get update ... ..."
-
在RUN命(ming)令執(zhi)行完畢后,會(hui)將當前層(ceng)目(mu)錄進行壓縮從而形成新鏡(jing)像中的(de)新的(de)一(yi)層(ceng), 同時(shi)為下一(yi)層(ceng)提供(gong)基礎(chu)鏡(jing)像;
-
如果 Dockerfile 中包含其它命令,就以之(zhi)前(qian)構(gou)建的(de)層次為基礎,從第(di)二步(bu)開始重復創建新層,直(zhi)到(dao)完成所有語句后(hou)退出;
-
在(zai) Dockerfile 中包含的所(suo)有指令(ling)命令(ling)執行完畢后鏡(jing)像構建完成,并(bing)為該鏡(jing)像打上Tag
2. 鏡像存儲
2.1 本地存(cun)儲
當Docker 在構(gou)建完鏡像(xiang)后會將其(qi)存儲在Docker 本(ben)地存儲家目錄中,默認情(qing)況即/var/lib/docker/
一個image 包含(han) Manifest 、images Index 、 Layer Filesystem、Image Configuration
對于(yu)鏡像存儲路徑最重要的默認路徑下(xia)(xia)的image 和 overlay2 這(zhe)個(ge)兩個(ge)目錄(lu),容器的元數(shu)據存放在(zai) image 目錄(lu)下(xia)(xia),容器的 layer 數(shu)據則存放在(zai) overlay2 目錄(lu)下(xia)(xia)。
/var/lib/docker/image/overlay2/repositories.json
當我們 docker run 一個容器的時(shi)候也用到這(zhe)個文件去(qu)索引本地(di)是否存(cun)在該鏡像,沒有(you)鏡像的話就自動去(qu) pull 這(zhe)個鏡像。
/var/lib/docker/image/overlay2/imagedb/content/sha256
存放目錄名為鏡像id內容是(shi)image config
2.2 容器在磁盤的存儲
容器(qi)的文(wen)件系統分為三(san)層(ceng): - r/o層(ceng):也就是(shi)鏡像(xiang)層(ceng) - init層(ceng):啟動容器(qi)時(shi)的參(can)數 - r/w層(ceng):可讀(du)寫層(ceng)
前面我們知(zhi)道(dao)鏡像存儲在/var/lib/docker/overlay2下面,這里不僅包含(han)了(le)只讀(r/o)層,init層和r/w層都在這個(ge)里面。
運行一(yi)個容器會返回(hui)一(yi)個容器id. 通過(guo)這(zhe)個id,我們能在/var/lib/docker/image/overlay2/layerdb/mounts目錄下找到該容器(qi)的信息:
2.3 查找(zhao)本地鏡像(xiang)的過程
1. 查找(zhao)/var/lib/docker/image/overlay2/repositories.json文(wen)件(jian),找(zhao)到對應版本的(de)imageId
2. 根據imageId在/var/lib/docker/image/overlay2/imagedb/content/sha256文(wen)件,文(wen)件名為imageId,內容是對應鏡像配置(zhi)(image.config)
3. 根據Image.config內(nei)的diff_id 到image/overlay2/layerdb/sha256 查找,根據chainID和diff_id的計算公式
chaninid(1) = diffid(1) chainid(n) = sha256(chain(n-1) diffid(n) )
4. 上述(shu)計算可以獲取(qu)各個不同鏡像層(ceng)在(zai) /var/lib/docker/overlay2 目錄下各個鏡像層(ceng)的uuid目錄
5. 上述uuid目錄下的diff 就(jiu)是(shi)各(ge)個鏡像層的文件系(xi)統
3 鏡像id梳理
imageID是(shi)對Image Configuration文件的(de)sha256哈希后的(de)得(de)到
manifest_digestId是對docker pull拉(la)取(qu)鏡像(xiang)的(de)manifest文(wen)件的(de)sha256哈(ha)希得到的(de)字符串
layer_diffId是對layer文(wen)件(.tar)sha256哈希得到的id
manifest_layer_digest是對壓縮后的layer文件(.tar.gz) sha256哈希的到id
chainId 計算(suan)diff_id獲取,公式:chaninid(1) = diffid(1) chainid(n) = sha256(chain(n-1) diffid(n) )
cache_id 宿(su)主機隨(sui)機生(sheng)成的uuid