1、分層的映象
我們可以去下載一個映象,注意觀察下載的日誌輸出,可以看到Docker的映象是一層一層的在下載。
思考:為什麼Docker映象要採用這種分層的結構呢?
最大的好處,我覺得莫過於是資源共享了!
比如有多個映象都從相同的Base
映象構建而來,那麼宿主機只需在磁碟上保留一份Base
映象,同時記憶體中也只需要載入一份Base
映象,這樣就可以為所有的容器服務了,而且映象的每一層都可以被共享。
檢視映象分層的方式可以通過docker image inspect 映象名
命令,如下:
[root@192 /]# docker image inspect redis:latest
[
{
"Id": "sha256:621ceef7494adfcbe0e523593639f6625795cc0dc91a750629367a8c7b3ccebb",
"RepoTags": [
"redis:latest"
],
... # 省略
... # 省略
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864",
"sha256:8e14cb7841faede6e42ab797f915c329c22f3b39026f8338c4c75de26e5d4e82",
"sha256:1450b8f0019c829e638ab5c1f3c2674d117517669e41dd2d0409a668e0807e96",
"sha256:f927192cc30cb53065dc266f78ff12dc06651d6eb84088e82be2d98ac47d42a0",
"sha256:a24a292d018421783c491bc72f6601908cb844b17427bac92f0a22f5fd809665",
"sha256:3480f9cdd491225670e9899786128ffe47054b0a5d54c48f6b10623d2f340632"
]
},
... # 省略
}
]
可以看到RootFS
屬性中的Layers
引數中,每一行代表一個映象層,每個一映象層都包含著一些操作步驟,最終合併成一個我們需要的系統環境和服務。
2、加深理解
所有的Docker映象都起始於一個基礎映象層,當進行修改或增加新的內容時,就會在當前映象層之上,建立新的映象層。
舉一個簡單的例子,假如基於Ubuntu Linux 16.04
建立一個新的映象,這就是新映象的第一層;如果在該映象中新增Python包,就會在基礎映象層之上建立第二個映象層;如果繼續新增一個安全補丁,就會建立第三個映象層。
該映象當前已經包含3個映象層,如下圖所示(這只是一個用於演示的很簡單的例子)。
在新增額外的映象層的同時,映象始終保持是當前所有映象的組合,理解這一點非常重要。下圖中舉了一個簡單的例子,每個映象層包含3個檔案,而整體的映象包含了來自兩個映象層的6個檔案。
上圖中的映象層跟之前圖中的略有區別,主要目的是便於展示檔案。
下圖中展示了一個稍微複雜的三層映象,在外部看來整個映象只有6個檔案,這是因為最上層中的檔案7是檔案5的一個更新版本。
這種情況下,上層映象層中的檔案覆蓋了底層映象層中的檔案。這樣就使得檔案的更新版本作為一個新映象層新增到映象當中。
Docker通過儲存引擎(新版本採用快照機制)的方式來實現映象層堆疊,並保證多映象層對外展示為統一的檔案系統。
Linux上可用的儲存引擎有AUFS
,Overlay2
,Device Mapper
,Btrfs
以及ZFS
。顧名思義,每種儲存引擎都基於Linux中對應的檔案系統或者塊裝置技術,並且每種儲存引擎都有其獨有的效能特點。
Docker在Windows上僅支援windowsfilter
一種儲存引擎,該引擎基於NTFS
檔案系統之上實現了分層和Cow
。
如上邊的三層映象,Docker最終會把所有映象層堆疊併合並,對外提供統一的檢視,如下圖。
3、特別說明
Docker映象都是隻讀的,當容器啟動時,一個新的可寫層被載入到映象的頂部,只有這個頂部是可寫的。
而這一層就是我們通常說的容器層,容器之下的都叫映象層。
如下圖:
下面這張圖更加形象: