今天要開始了解 Docker 世界了,首先會先說明 Docker 的基本概念,接著再以驗證指令 docker run hello-world
為例,解釋背後細節。
Docker 的世界裡,有三個主要元件如下:
執行 Docker 的主機,稱為 Host。
在 host 執行 docker run
指令時,Docker 會操作這三個元件來完成任務。首先來了解這三個元件。
Image 包裝了一個執行特定環境所需要的資源。
每個 image 都有獨一無二的 digest,這是從 image 內容做 sha256 產生的。這個設計能讓 image 無法隨意改變內容,維持資料一致性。
雖然 image 裡有必要的資源,但它無法獨立執行,必須要靠 container 間接執行。
基於 image 可以建立出 Container。
它的概念像是建立一個可讀寫內容的外層,架在 image 上。實際存取 container 會經過可讀寫層與 image,因此看到的內容會是兩者合併後的結果。
Container 特性跟 image 不一樣,因為有可讀寫層,所以 container 可以讀寫,也可以拿來執行。
Repository 是存放 image 的空間。
Docker 設計類似分散式版本控制的方法來存放各種 image。而分散式架構就會有類似 git 的 pull / push 行為,實際做的事也跟 git 類似:為了要跟遠端的 repository 同步。
另一個與 repository 很像,但容易混用的名詞為 Registry,後者涵蓋範圍更廣,包含了更多 repository 與身分驗證功能等,通常比較常討論的也是 registry。
目前 Docker 預設的 registry 為 DockerHub,大多數程式或服務的 image 都能在上面找得到。
Image、container、repository 之間的關係就像光碟一樣:早期世紀帝國等光碟遊戲,會需要搭配其他可讀寫空間(如硬碟),才有辦法執行。
安裝好環境後,第一次執行驗證指令 docker run hello-world
範例如下:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:7f0a9f93b4aa3022c3a4c147a449bf11e0941a1fd0bf4a8e6c9408b2600777c5
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
docker run
有明確執行的意思。回頭看一開始的元件說明可以了解,docker run
會建立一個 container 並執行;而因為 container 需要基於 image 建立,所以 docker run
有個必要的參數是 image 名稱,即 hello-world
。
它的訊息非常長,但實際上可以分為兩個區塊:
首先先確認 hello-world
是否存在於本機的 repository,本機找不到的話,就需要從遠端的 repository 下載。
下面即為找不到 image,並從遠端下載的訊息:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:7f0a9f93b4aa3022c3a4c147a449bf11e0941a1fd0bf4a8e6c9408b2600777c5
Status: Downloaded newer image for hello-world:latest
Docker 設計 image 名稱會包含 registry 的路徑,若沒有的話,則預設是 DockerHub。
確認好 Image 存在或下載好後,即可建立 Container 並執行。
docker run
預設的行為是:
以本範例來說,資訊顯示完回到命令提示字元時,上面三個步驟就都完成了。步驟二在執行過程很明顯,而步驟一與三所提到的 container 可以使用 docker ps
查看:
docker ps -a
裡面的訊息如下:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d7e00198a56 hello-world "/hello" 12 seconds ago Exited (0) 11 seconds ago relaxed_bhabha
docker ps
可以看 container 的概況,除了列出有哪些 container 外,也有其他欄位了解 container 相關資訊。
首先可以注意到 STATUS
欄位狀態為 Exited (0)
,後面的數字為程式結束後回傳的狀態碼,通常 0 為正常結束,非 0 則是有錯誤。
最開頭的 CONTAINER ID
與最後的 NAMES
是獨一無二的,可以多執行幾次 docker run
,接著就會看到很多不一樣名字的 container。
若一直不斷執行 docker run hello-world
的話,就會造成 container 數量不斷成長。雖然使用到容量不多,但在管理上多少會造成困擾。
最簡單的方法是,沒有要再用的 container 就移除它。以上面的範例為例,移除 container 的指令如下:
# 使用 CONTAINER ID: 6d7e00198a56 或 NAMES: relaxed_bhabha 皆可
docker rm 6d7e00198a56
# 移除完使用 docker ps 再檢查一次
docker ps -a
docker rm
是移除 container 的指令,只要 container 不是處於 Up
正在執行中的狀態,即可使用 docker rm
移除。
docker run
使用 IMAGE
建立新的 container 並執行指令,用法如下:
docker run IMAGE
IMAGE
會先從本機 repository 找,有的話就執行;若沒有的話,會到遠端 repository 下載並執行。
docker ps
列出已建立的 container。
docker ps
-a|--all
列出所有的 containerdocker rm
移除指定的 container,用法如下:
docker rm CONTAINER [CONTAINER...]
CONTAINER
可以是 docker ps
查到的 CONTAINER ID 或 NAMES。若需要移除多個 container,可以使用空白隔開每個 container 名稱,如:
docker rm container_a container_b
Image、container、repository,三個元件之間的關係,可以畫成示意圖如下:
今天的說明搭配此圖,相信讀者能更了解 docker run
與元件如何互動。
docker run
指令執行 hello-world
imagedocker ps
指令,觀察 container 狀態docker rm
指令,整理 container 列表