iT邦幫忙

2022 iThome 鐵人賽

DAY 3
0
DevOps

那些關於 docker 你知道與不知道的事系列 第 3

Day 03: Container 是什麼?

  • 分享至 

  • xImage
  •  

在上一篇中我們準備好了實驗環境,現在就來試試看怎麼啟動一個 container,docker 最厲害的一點就是將啟動 container 這件事變得很簡單,例如,只需要在我們的 Host(備註1) 上執行以下指令就可以建立一個 container:

$ docker run -it alpine ash
  • docker run: 這是一個 docker 指令,執行這個指令可以讓 docker 啟動一個新的 contaier,在這後面的都是 docker run 的相關參數,其相關參數還不少,可以參考官網說明: https://docs.docker.com/engine/reference/commandline/run/
  • 參數 -it 中的 -i: 這是要啟動一個互動模式(interactive),以用來保持標準輸入的開放。
  • 參數 -it 中的 -t: 這是讓 docker 分配一個虛擬終端機(pseudo-TTY),並且綁定到容器的標準輸出上。
  • alpine: 這是用來啟動這個 container 的「依據」,或者說「樣版」。
  • ash: 即為我們要在這個 container 中執行的命令,他是在 alpine 中使用的 shell。

當我們執行了指令後,會發現我們的 terminal 變成 / # 了,這時候不管是執行 pwd 或是 ls 等指令,會發現跟你在執行 docker run 之前的地方或檔案都不一樣了,彷彿進入了另外一台主機。讓我們執行看看 ps aux 觀察看看:

/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 ash
   11 root      0:00 ps aux

可以看到這裡只有兩個 process,第一個是我們在啟動 container 時指定要執行的 ash shell,第二個 process 就是我們正在執行的這個 ps aux,而且其 PID 分別是 1 跟 11。

這時候讓我們用另外一個 terminal 登入 並且重新執行一次 ps aux,正常來說你應該會看到非常多個 process 才對,很顯然 container 裡跟我們的 Host 是不同的兩個世界,對吧!

讓我們更進一步觀察一下,在 Host 中執行:

$ ps aux | grep ash
ubuntu      1604  0.0  4.9 1273700 47772 pts/0   Sl+  14:09   0:00 docker run -it alpine ash
root        1655  0.0  0.1   1712  1056 pts/0    Ss+  14:09   0:00 ash
ubuntu      1853  0.0  0.0   8168   724 pts/1    R+   14:28   0:00 grep --color=auto ash

至少看到三個跟 ash 有關的 process,第一個是我們在執行 docker 指令,第三個是我們在 grep ash 這個關鍵字,這兩個都沒什麼特別的,但第二個就很有趣了,他是一個 ash shell,那讓我們在 Host 中執行看看 ash:

$ ash

Command 'ash' not found, but can be installed with:

sudo apt install ash

咦,在我們的 Host 中根本沒有 ash 可以執行啊,那剛剛那個 ash 是哪裡來的呢?

其實這個 ash 就是 container 中的那一個 process。要怎麼驗證這件事呢?我們先用以下指令(備註2)找到目前執行中的 container 的 id:

$ docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
f9baa6f78fc9   alpine    "ash"     23 minutes ago   Up 23 minutes             zealous_goldstine

透過 docker container ls 這個指令,可以列出目前有在執行中的 container(備註3),目前我們只有一個 container 在執行中,所以只會看到一列資料,這一列資料中的第一個欄位就是 container id,可以用來辨識一個 container。

接下來我們用 inspect 這個指令來查看一下這個 container:

$ docker conatiner inspect f9baa6f78fc9
...(這裡應該會看到一大長串以 JSON 格式呈現的資訊)

雖然資訊蠻多的,但鼓勵有興趣的人沒事可以多看看,這次我們先重點放在 State 這一個區塊,這時候可以用 format 這個參數來指令要看的內容(備註4 & 5):

docker container inspect  --format='{{json .State}}' f9baa6f78fc9 | jq
{
  "Status": "running",
  "Running": true,
  "Paused": false,
  "Restarting": false,
  "OOMKilled": false,
  "Dead": false,
  "Pid": 1655,
  "ExitCode": 0,
  "Error": "",
  "StartedAt": "2022-09-18T14:09:26.743771986Z",
  "FinishedAt": "0001-01-01T00:00:00Z"
}

這邊有一個有趣的欄位 PID,他的數字是 1655,還記得我們剛剛在 Host 執行 ps aux | grep ash 看到的結果嗎?第二個 process 的 PID 是不是就是 1655 呢?

root        1655  0.0  0.0   1712   148 pts/0    Ss+  14:09   0:00 ash

不要懷疑啦,他們就是同一個,所以說啊,神秘的 container,說穿了其實不過就是 Host 中一個 process 而已喔,當然,他不是單純的 process,我們對他動了很多手腳,如果撇開那些,container 其實就只是一個 process 而已(對,我知道我重複寫了這句第二次,但我甚至還想要說第三次...)。

網路上或面試的時候,經常會討論到的一題是「container 跟 VM (virtual machine) 有什麼不一樣」,我自己總覺得這樣有點像是在問熱狗跟狗有什麼不一樣...但也不能這樣想,container 的本質是一個 process,但他的一些特性跟用起來的感覺,的確很像是 VM,這之後再討論了。

到目前為止,大家可以知道 container 其實就是一個在 Host 上執行的 process 而已,但在我們的 Host 中明明沒有 ash 這個指令,他是怎麼被執行出來的呢?又為什麼在 container 中看到的 process 只有兩個?PID 編號也跟 Host 中完全不一樣呢?這些就讓我們後續再繼續研究下去嚕~


備註:

  1. 接下來都會把我們用來做實驗的 AWS EC2 instance 稱為 Host,好用來區別是用來啟動 container 的那台主機環境,還是在 container 裡。
  2. 也可以用 docker ps ,有一樣的結果。
  3. docker container ls -a 或是 docker ps -a 可以列出所有的 container,包括執行中或是已經停止的。
  4. 關於 format 的用法可以參考 https://docs.docker.com/engine/reference/commandline/inspect/
  5. 由於用了 format 後,輸出的結果會是一個字串,這時候可以用 jq 這個指令去把那串文字轉成比較好閱讀的 JSON 格式,但這個指令需要另外安裝 sudo apt install jq,蠻推薦裝一下的,好用。

上一篇
Day 02: 實驗環境準備
下一篇
Day 04: 什麼是 image?
系列文
那些關於 docker 你知道與不知道的事32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
HoiDam
iT邦新手 5 級 ‧ 2022-10-18 14:59:34

那熱狗跟狗有什麼不一樣 (被揍

小賴 iT邦新手 4 級 ‧ 2022-10-19 12:09:39 檢舉

一個熱的一個不...好像也是熱的,那結論就是沒什麼不一樣...

HoiDam iT邦新手 5 級 ‧ 2022-10-20 09:27:41 檢舉

/images/emoticon/emoticon73.gif

我要留言

立即登入留言