1. 程式人生 > >Docker 架構及工作原理

Docker 架構及工作原理

通過下圖可以得知,Docker 在執行時分為 Docker 引擎(服務端守護程序)客戶端工具,我們日常使用各種 docker 命令,其實就是在使用 客戶端工具Docker 引擎 進行互動。

Client 客戶端

Docker 是一個客戶端-伺服器(C/S)架構程式。Docker 客戶端只需要向 Docker 伺服器或者守護程序發出請求,伺服器或者守護程序將完成所有工作並返回結果。Docker 提供了一個命令列工具 Docker 以及一整套 RESTful API。你可以在同一臺宿主機上執行 Docker 守護程序和客戶端,也可以從本地的 Docker 客戶端連線到執行在另一臺宿主機上的遠端 Docker 守護程序。

Host 主機(Docker 引擎)

一個物理或者虛擬的機器用於執行 Docker 守護程序和容器。

Image 映象

什麼是 Docker 映象?簡單的理解,Docker 映象就是一個 Linux 的檔案系統(Root FileSystem),這個檔案系統裡面包含可以執行在 Linux 核心的程式以及相應的資料。

通過映象啟動一個容器,一個映象就是一個可執行的包,其中包括執行應用程式所需要的所有內容:包含程式碼,執行時間,庫,環境變數和配置檔案等。

Docker 把 App 檔案打包成為一個映象,並且採用類似多次快照的儲存技術,可以實現:

  • 多個 App 可以共用相同的底層映象(初始的作業系統映象);
  • App 執行時的 IO 操作和映象檔案隔離;
  • 通過掛載包含不同配置/資料檔案的目錄或者卷(Volume),單個 App 映象可以用來執行無數個不同業務的容器。

Container 容器

映象(Image)和容器(Container)的關係,就像是面向物件程式設計中的類和例項一樣,映象是靜態的定義,容器是映象執行時的實體。容器可以被建立、啟動、停止、刪除、暫停等。

Docker 面向物件
容器 物件
映象

映象分層

Docker 支援通過擴充套件現有映象,建立新的映象。實際上,Docker Hub 中 99% 的映象都是通過在 base 映象中安裝和配置需要的軟體構建出來的。

從上圖可以看到,新映象是從 base 映象一層一層疊加生成的。每安裝一個軟體,就在現有映象的基礎上增加一層。

映象分層最大的一個好處就是共享資源。比如說有多個映象都從相同的 base 映象構建而來,那麼 Docker Host 只需在磁碟上儲存一份 base 映象;同時記憶體中也只需載入一份 base 映象,就可以為所有容器服務了。而且映象的每一層都可以被共享。

如果多個容器共享一份基礎映象,當某個容器修改了基礎映象的內容,比如 /etc 下的檔案,這時其他容器的 /etc 是不會被修改的,修改只會被限制在單個容器內。這就是容器 「Copy-on-Write」 特性。

可寫的容器層

當容器啟動時,一個新的可寫層被載入到映象的頂部。這一層通常被稱作“容器層”,“容器層”之下的都叫“映象層”。

所有對容器的改動 - 無論新增、刪除、還是修改檔案都只會發生在容器層中。只有「容器層是可寫的,容器層下面的所有映象層都是隻讀的」。

映象層數量可能會很多,所有映象層會聯合在一起組成一個統一的檔案系統。如果不同層中有一個相同路徑的檔案,比如 /a,上層的 /a 會覆蓋下層的 /a,也就是說使用者只能訪問到上層中的檔案 /a。在容器層中,使用者看到的是一個疊加之後的檔案系統。

檔案操作 說明
新增檔案 在容器中建立檔案時,新檔案被新增到容器層中。
讀取檔案 在容器中讀取某個檔案時,Docker 會從上往下依次在各映象層中查詢此檔案。一旦找到,立即將其複製到容器層,然後開啟並讀入記憶體。
修改檔案 在容器中修改已存在的檔案時,Docker 會從上往下依次在各映象層中查詢此檔案。一旦找到,立即將其複製到容器層,然後修改之。
刪除檔案 在容器中刪除檔案時,Docker 也是從上往下依次在映象層中查詢此檔案。找到後,會在容器層中「記錄下此刪除操作」。(只是記錄刪除操作)

只有當需要修改時才複製一份資料,這種特性被稱作 Copy-on-Write。可見,容器層儲存的是映象變化的部分,不會對映象本身進行任何修改。

總結下來就是:容器層記錄對映象的修改,所有映象層都是隻讀的,不會被容器修改,所以映象可以被多個容器共享。

Volume 資料卷

實際上我們的容器就好像是一個簡易版的作業系統,只不過系統中只安裝了我們的程式執行所需要的環境,前邊說到我們的容器是可以刪除的,那如果刪除了,容器中的程式產生的需要持久化的資料怎麼辦呢?容器執行的時候我們可以進容器去檢視,容器一旦刪除就什麼都沒有了。

所以資料卷就是來解決這個問題的,是用來將資料持久化到我們宿主機上,與容器間實現資料共享,簡單的說就是將宿主機的目錄對映到容器中的目錄,應用程式在容器中的目錄讀寫資料會同步到宿主機上,這樣容器產生的資料就可以持久化了,比如我們的資料庫容器,就可以把資料儲存到我們宿主機上的真實磁碟中。

Registry 註冊中心

Docker 用 Registry 來儲存使用者構建的映象。Registry 分為公共和私有兩種。Docker 公司運營公共的 Registry 叫做 Docker Hub。使用者可以在 Docker Hub 註冊賬號,分享並儲存自己的映象。

Docker 公司提供了公共的映象倉庫 https://hub.docker.com(Docker 稱之為 Repository)提供了龐大的映象集合供使用。

一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標籤(Tag);每個標籤對應一個映象。

通常,一個倉庫會包含同一個軟體不同版本的映象,而標籤對應該軟體的各個版本。我們可以通過 「<倉庫名>:<標籤>」 的格式來指定具體是這個軟體哪個版本的映象。如果不給出標籤,將以 「latest」 作為預設標籤。

總結

Docker 官網寫著這樣一句話:「Build and Ship any Application Anywhere」,再結合剛才我們所理解的內容,總結下來就是:「一次構建,到處執行。」

此外,Docker 公司提供了公共的映象倉庫 https://hub.docker.com(Docker 稱之為 Repository),GitHub connect,自動構建映象,大大簡化了應用分發、部署、升級流程。加上 Docker 可以非常方便的建立各種自定義的映象檔案,這些都是 Docker 成為最流行的容器技術的重要因素。

通過以上這些技術的組合,最後的結果就是:絕大部分應用,開發者都可以通過 docker build 建立映象,通過 docker push 上傳映象,使用者通過 docker pull 下載映象,使用 docker run 執行容器應用。使用者不再需要去關心如何搭建環境,如何安裝,如何解決不同發行版的庫衝突——而且通常不會消耗更多的硬體資源,不會明顯降低效能。

從下文開始,我們就進入 Docker 實操部分,先從 Docker 的安裝及配置映象加速講起,然後再學習一些映象和容器最常用的命令。

本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

大家可以通過 分類 檢視更多關於 Docker 的文章。