首頁 > 軟體

Docker容器實戰之映象與容器的工作原理

2022-05-24 14:00:24

一. bootfs和rootfs

通常而言,Linux的作業系統由兩類檔案系統組成:bootfs(boot file system)和rootfs(root file system),它們分別對應著系統核心與根目錄檔案。bootfs層主要為系統核心檔案,這層的內容是無法修改的。當我們的系統在啟動時會載入bootfs,當載入完成後整個核心都會存到記憶體中,然後系統會將bootfs解除安裝掉。而rootfs層則包含了系統中常見的目錄和檔案,如/bin,/etc,/proc等等。

Docker的映象技術可以使用宿主機的bootfs層,這使得映象本身只需要封裝rootfs層所需要的檔案和工具即可。因此,映象可以根據需要進行客製化化封裝,減少佔用的儲存空間,如部分極精簡的映象只有幾MB大小。

在不同Linux發行版本中,它們之間的主要區別在於rootfs層,比如ubuntu使用apt管理軟體,而Centos使用yum方式。而在核心層面,兩者的差別並不大。因此,我們可以在一臺主機上同時支援不同Linux系統的映象而不出現報錯,如同時啟動Centos和Ubuntu的容器。

但需要注意的是,不管容器使用什麼系統的映象,實際的核心版本都與映象無關,都為宿主機的核心。如ubuntu16.04 的容器跑在Centos7.x的宿主機上,雖然ubuntu的核心版本是4.x.x,但我們在容器中會看到核心為centos 7.x 的核心,即 3.x.x。如果是對核心版本的要求的程式,可能會因此受到影響。

二. 映象結構

Docker映象採用分層的結構,由一些鬆耦合的唯讀層堆疊而成,並對外展示為一個統一的物件。所有的映象都開始於一個基礎的映象層,當我們進行修改或內容新增時,會在映象層上面建立新的一層。

最底層通常為基礎層映象,然後再層層疊加上來,比如安裝一個Python軟體,此時會在基礎層上面新增一個新的層,上面包含了我們所安裝的Python程式。

映象做為所有映象層的組合,如果映象中有相同路徑的檔案,則上層映象會覆蓋下層映象的內容,最終展示為所有層的資料彙總。

如下圖所示,由於第二層的檔案2與第一層具有相同的檔案路徑,則映象將以第二層的檔案2內容進行展示,第一層只有檔案1會被顯示。

我們再來回顧一下前面映象拉取時的輸出內容,Pull complete結尾的每一行代表映象中某個被拉取的層,每個層級通過一個唯一的ID進行標識。

$ docker pull nginx:1.20
1.20: Pulling from library/nginx
5eb5b503b376: Pull complete
cdfeb356c029: Pull complete
d86da7454448: Pull complete
7976249980ef: Pull complete
8f66aa6726b2: Pull complete
c004cabebe76: Pull complete
Digest: sha256:02923d65cde08a49380ab3f3dd2f8f90aa51fa2bd358bd85f89345848f6e6623
Status: Downloaded newer image for nginx:1.20
docker.io/library/nginx:1.20

映象層的鬆耦合代表著它不屬於某個映象獨有,當不同映象包含相同的層時,系統只會儲存該層的一份內容,這是Docker映象的重要特點,這樣的好處有利於減少儲存空間的佔用。如下所示,當我們拉取另一個版本的Nginx映象時,其中ID號為5eb5b503b376的層已經存在,則會顯示為Already exists,直接使用此映象層。

$ docker pull nginx:1.21
1.21: Pulling from library/nginx
5eb5b503b376: Already exists
1ae07ab881bd: Pull complete
78091884b7be: Pull complete
091c283c6a66: Pull complete
55de5851019b: Pull complete
b559bad762be: Pull complete
Digest: sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
Status: Downloaded newer image for nginx:1.21
docker.io/library/nginx:1.21

三. 容器層

我們前面說到映象層是唯讀模板,那麼當我們使用映象生成容器時,為什麼又能寫入資料呢?這個問題的答案涉及到一個概念:容器層。

當容器啟動時,會有一個新的可寫層被載入到映象的頂部,這一層通常被稱為容器層。所有對容器的修改都會發生在容器層,只有容器層是可寫入的,容器層以下的映象層都是唯讀的。

當我們對容器進行操作時,底層的工作原理如下:

讀取檔案:當容器需要讀取檔案時,會先在容器層尋找,如果沒有發現,則會從最上層的映象層往下尋找,當找到檔案後讀取到記憶體使用。

增加檔案:當增加檔案時,檔案會直接寫到最上面容器層,不會影響到映象層內容。所以,當我們將容器刪除時,容器中的檔案也會隨著消失。

修改檔案:此時,如果該檔案是在容器層的,則會直接修改。否則的話,Docker會從上往下依次在各層映象中查詢此檔案 ,當找到後將其複製到容器層中,並進行修改。這被稱為容器的寫時複製特性(Copy-on-Write),這個技術保證了我們對容器的修改不會影響到底層的映象,也實現了一個映象可以被多個容器共用。

刪除檔案:當我們需要刪除檔案時,Docker也是由上往下尋找該檔案 ,如果在容器層的檔案會被直接刪除,而在映象層的檔案則會被標記,此時在容器將不會再出現此檔案,但映象中的檔案並不會做更改。

四. 聯合檔案系統​

關於映象與容器功能的實現,依賴其使用了聯合檔案系統(UnionFS)技術,這是一種分層、輕量級並且高效能的檔案系統。Docker 目前支援的聯合檔案系統包括 ​​OverlayFS​​​, ​​AUFS​​​, ​​VFS​​​ ​​Device Mapper等​​,而預設的儲存驅動為Overlay2。

到此這篇關於Docker容器實戰之映象與容器的工作原理的文章就介紹到這了,更多相關Docker 映象與容器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com