1. 程式人生 > >docker映象儲存詳解

docker映象儲存詳解

映象來源

映象需要存在於本地倉庫中才能用其啟動容器,映象通常有以下三種來源:

l  使用dockerfile構建

l  匯入從其它倉庫save的映象

l  從遠端倉庫pull映象

其它還有對容器進行commit等,但它們的原理都包含在了以上3種方式之中。

無論採用哪種方式,映象的最初來源一般都是通過dockerfile構建而來,因此首先分析dockerfile構建映象的過程,進而幫助我們瞭解映象是如何儲存和使用的.

docker可以採用不同的儲存驅動來儲存和使用映象,目前內建的驅動有:

我們採用的是overlay2,以此為例進行分析的講解,基本原理大同小異。

關係概念:

diffID:映象每層次內容的摘要,反映了單個層次內容的資訊

chainID:映象每層次的鏈ID,演算法為H(N)=H(N-1)sha256(n),與其自身和所有的父層次相關,反映了祖先鏈。映象層次的重用需要chainID相同,如果只是diffID相同則不能命中。

cacheID:映象內容實際存放的位置,是一個隨機值,與chainID的對應關係見下面的目錄說明

目錄結構

docker的根工作目錄一般是/var/lib/docker

首先看一下涉及到的相關目錄:

/var/lib/docker/image/<graphdriver>:儲存映象管理資料的目錄,以使用的儲存驅動命名

/distribution:pull的映象相關元資料

/imagedb:映象資料庫

/content:構成映象的每層次的配置資料

        /sha256/<IMAGE-ID>:每映象層次的配置digest,也就是映象ID.(參考原始碼:github.com/docker/docker/image/store.go:store.Create(config[]byte)(ID, error))

/metadata:

                                                         /sha256/<IMAGE-ID>:具有父映象的層次ID,沒有父映象的基礎映象在此目錄沒有內容

                                                                           /parent:父映象ID(參考原始碼

:github.com/docker/docker/daemon/build.go:Daemon.CreateImage(config[]byte,parent string,platform string)(builder.Image, error))

                                                         /layerdb:映象每layer元資料

                                                                 /sha256

                                                                           /<chainID>:每個layer的chainID

                                                                                    /cache-id:本layer在下面所對應的cache-id

                                                                                    /diff:本層次的diffID

                                                                                    /size:本層次的大小

                                                                                    /parent:父layer chainID (moby/daemon/commit.go:Daemon.Commitmoby/layer/ro_layer.go:storeLayer)

                                                                 /mounts:容器的RW layer資訊

                                                                              /<container-id>:

                                                                                    /init-id:讀寫層的cache-id

                                                                                   /cache-id:容器的讀寫層mount-id

                                                                                    /parent:父layer的chainID

/var/lib/docker/<graphdriver>:映象的所有layer和容器rwlayer的位置 

                                                        /l:符號連結目錄,每一個符號連結檔案連結向下面的cache-id,一一對應,使用這個符號連結的目的是因為mount args最大限制為一個pagesize.

                                                        /cache-id:layer的cache-id為一個隨機值.(參考原始碼:moby/layer/layer_unix.go:layerStore.mountID(namestring)string)

                                                                 /diff:本layer所包含的實際檔案系統資料

                                                                 link:儲存本cache-id所對應的符號連結

                                                                 lower:本layer的所有父layer所對應的符號連結

                                                                 /megerd:本layer及所有父layer共同呈現的目錄

                                                                 /work:overlay2檔案系統使用的目錄(參考原始碼:moby/daemon/graphdriver/overlay2/overlay.go:Driver.CreateReadWrite(id,parent,opts)error)

                                                      /cache-id-init:容器的init層目錄:(moby/layer/layer_store.go:layerStore.initMount(graphID,   parent, mountLabel,initFunc,storageOpt)(string,error))


映象構建


映象匯出

使用docker save命令匯出映象

映象內容:

.

├──816c0fa43179255d36592e0ede6ed020793130645eaf063fa27c5544ae46bb6b

│   ├── json

│   ├── layer.tar

│   └── VERSION

├──b8efb18f159bd948486f18bd8940b56fd2298b438229f5bd2bcf4cedcf037448.json

├── bcb8dea8dbd93bef252214259890b19a6a4886bc333d0b16f98a40b5fd063c27

│   ├── json

│   ├── layer.tar

│   └── VERSION

├──e1a9983e063a540bd4072c352ab6bc72b63ceebf311255e9d16de34eee018471

│   ├── json

│   ├── layer.tar

│   └── VERSION

└── manifest.json

b8efb18f159bd948486f18bd8940b56fd2298b438229f5bd2bcf4cedcf037448.json:

<IMAGE-ID>.json:映象配置

manifest.json:清單檔案

type manifestItem struct {
   Config       string
   RepoTags     []string
   Layers       []string
   Parent       image.ID                                 `json:",omitempty"`
   LayerSources map[layer.DiffID]distribution.Descriptor `json:",omitempty"`
    }


816c0fa43179255d36592e0ede6ed020793130645eaf063fa27c5544ae46bb6b:

映象每一層次的內容,這個ID是在匯出時用原有層次資訊生成的臨時映象所做的摘要。對應清單檔案中的Layers.(參考程式碼:docker/docker/image/tarexport/save.go)

json: V1Image結構體

VERSION:版本資訊,1.0

layer.tar:實際的檔案系統內容

映象匯入

映象匯出的逆過程。

參考程式碼:(image/tarexport/load.go:Load)

1.        建立臨時目錄(/tmp/XRFMG/docker-import-),對映象壓縮包進行解壓.

2.        讀取manifest.json檔案,獲取config檔名,檔名為<IMAGE-ID>.json

3.        從配置檔案中獲取所有層的diffIDS,遍歷所有diffIDS,依次載入

如果layer的chainID已經存在,則不再匯入.

如果layer的chainID不存在,則匯入.

匯入後判斷匯入layer的diffID與配置檔案中是否相等,不相等則報錯.