至今為止,我們已經用到了至少三種 Docker 指令,不過對 Docker 還沒有很全面地講解過,
因此今天就來用比較高層次的角度,來聊聊 Docker 世界中的各個子系統。
我有一個學習的技巧,如果對新東西不夠熟悉,就用心智圖把它們整理一下,嘗試呈現成樹狀或放射狀的架構圖,很快就會變得一目了然,
以下是我目前對 Docker 子系統的理解:
我把 Docker 分成了 7 個部分,
同時在簡介前,會從「為什麼要用 Docker」開始。
Docker 是虛擬化技術的一種,
而在 Docker 出現之前,存在並廣泛使用的虛擬技術是 Virtual Machine
,為的是把一台電腦切分成能裝載多個 OS (作業系統),並共享硬體資源,
而 Docker 則是在不同層級上的資源共享,VM 共享的是硬體,創造出虛擬的 OS,Docker 則是共享 OS 了,創造出虛擬的執行環境,
共享的層級從底層硬體拉到較高的 OS 層級,於是直接使 Docker (或說容器化技術) 得到了極度輕量及快速的可能性,而在 Docker, Inc. 與相關社群的貢獻下,形成了現在的容器化主流工具。
Docker 的環境本身,又可以被分成三層結構,
前幾天的文章中,我們會在終端機中用到 Docker 的 CLI 來建置及執行,CLI 本身就是 Client,所以實際上並不是我們的指令建置 Image,CLI 只是呼叫函式而已,
其中被呼叫的就叫 Daemon,Client 要求 Daemon 做事情,接著 Daemon 會再去使用更核心的 Docker 模組,剩下的則被我稱為 Kernel,例如 containerd
跟 runc
,所以其實 Daemon 也不是執行的角色,
為什麼要區分的這麼多層呢?這就稱為抽象層,是為了方便 Docker 本身被持續維護,因此分成了「櫃檯電話」、「櫃檯人員」、與「後勤人員」,
櫃檯電話總是不變,而客服人員接到電話後,把實際要處理的事情再傳達給後勤人員,於是三個部分就能被各自獨立地改進。
還記得 Dockerfile
嗎?這個檔案會定義一個 Image 的建置步驟,也就是定義執行的環境,
如果拿 RPG 遊戲來比喻,有點像是在「定義一個遊戲副本」,設定副本內的入口在哪裡,地圖有多大,王在哪裡之類的。
當我們把一個 Docker Image 跑起來時,就是像是進入一個遊戲副本,每一次的副本都是全新的,不同玩家進入的副本,雖然都是相同的內容,但並不是進入同一個副本,
副本本身的定義是 Image,而開始運行的副本就是 Container,副本間各自獨立。
Volume 的概念到目前為止都還沒有使用到,
先想像在遊戲副本的地圖上,有一個區域的內容,實際上是外部原本的遊戲世界,但跟副本內綁定,因此我們可以把東西放在這裡,外部也可以把東西放在這裡,地圖上的這塊空間就稱為 Volume,
我們很快就會看到玩具範例的。
幾乎所有應用程式都已經無法脫離網路了,
想像在遊戲中,進入副本的玩家不會跟世界完全脫鉤,例如在副本內的玩家還是有可能對外面的玩家傳遞私訊,
Docker 的網路就像是這個用途,可以在 Container 跟主機、或是 Container 跟 Container 之間建立出可以通訊的網路,當然,還是透過虛擬化的技術,去共用 OS 的網路資源。
大部分的應用程式,多多少少都會紀錄一些執行的過程,尤其是後端的程式,這些紀錄就稱為 Log,有點類似副本中玩家的足跡,
遊戲 GM 也許會想要知道玩家們通常怎麼攻略的,或是當副本有 Bug 時,有辦法得知錯誤的細節,這些線索就是從 Log 來的,
舉例 Node.JS 的 console.log
、或是 Python 的 print
,在 Docker 內印出的內容就會傳到 Docker 的 Log 中。
最後,很常見會以 Docker Compose 來定義一組 Container 的行為,透過定義成一個 YAMl 設定檔,可以方便地把一組 Container 跑起來,
進一步,還可以把這一份設定檔加入到版控系統中,大大增加了維護的方便性。