在上一篇中我們準備好了實驗環境,現在就來試試看怎麼啟動一個 container,docker 最厲害的一點就是將啟動 container 這件事變得很簡單,例如,只需要在我們的 Host(備註1) 上執行以下指令就可以建立一個 container:
$ docker run -it alpine ash
-it
中的 -i
: 這是要啟動一個互動模式(interactive),以用來保持標準輸入的開放。-it
中的 -t
: 這是讓 docker 分配一個虛擬終端機(pseudo-TTY),並且綁定到容器的標準輸出上。當我們執行了指令後,會發現我們的 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 中完全不一樣呢?這些就讓我們後續再繼續研究下去嚕~
備註:
docker ps
,有一樣的結果。docker container ls -a
或是 docker ps -a
可以列出所有的 container,包括執行中或是已經停止的。sudo apt install jq
,蠻推薦裝一下的,好用。