昨天介紹了如何和容器內的作業系統透過終端機進行溝通,而今天則會介紹關於容器的初始指令。
也攸關於容器在什麼時候會進入退出狀態。
容器的初始指令
這是昨天的範例:
$ docker container run --interactive --tty nginx bash
為什麼在 nginx 後面還要加上 bash 這個指令呢?
我們利用 Docker 提供的 --help
方法來看看,到底後面能夠接受什麼樣的參數呢?
$ docker container run --help
Usage: docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
....
可以看到 IMAGE 的後方還可以接受 COMMAND 的參數,而這個 COMMAND 就是容器啟動時會執行的指令。
那為什麼之前又不需要呢?是因為映像檔在設計的時候大部分都會給予一個 COMMAND 來當作初始指令,如果沒有輸入額外的 COMMAND 去取代的話,預計就會使用原本的。
而 nginx 這個映像檔原先的初始指令就是 nginx -g daemon off
,也就是啟動 nginx 的意思。
在上面的範例中,我們就是利用了 bash 來取代掉 nginx -g daemon off
這段初始指令,變成容器在啟動時執行 bash 這個命令處理器。
接著我們回到容器內部,再次輸入相同的指令,並且離開:
$ docker container run --interactive --tty nginx bash
root@d33940b87e66:/# exit
透過列出容器的指令,會發現這個容器竟然進入了退出狀態。
$ docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d3394...... nginx "/doc.. 7 sec.. Exited eleme...
容器的退出機制
還記得我們在一開始啟動 nginx 容器時,使用 Ctrl + C
的方式就使容器進入退出狀態吧?但為什麼這邊是退出了 bash 執行程序就退出容器了呢?
先說結論:
只有終止了初始指令所執行的程序,才會使容器進入退出狀態
這句話可能有點難以理解,但依照本書的方式,我們就是會不斷地進行驗證,來理解基本觀念。
在驗證上面那段結論之前,我們要先學會進入運作中的容器才有辦法進行驗證。
進入運作中的容器
剛剛的示範都是在第一次啟動容器時進入,但其實大部分時候程序是一直在執行,所以我們隨時都有進入容器的可能。
這邊我們先讓 nginx 在背景執行,接著試著進入內部:
$ docker container run --detach --publish 80:80 nginx
64d52ea0e08797aade7f86701b60ed903373f53713d6f7eca62...
$ docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64d52ea0... nginx "/doc.. 31 se.. Up 2.. 0.0.0.0:80->80/tcp hungry..
這邊確定了 nginx 正在背景執行,接著進入正在運作的容器:
$ docker container exec --interactive --tty 64d52 bash
root@64d52ea0e087:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@64d52ea0e087:/# exit
exit
進入後一樣用了 ls 這個 Linux 指令來查看容器中的檔案,並且輸入 exit 退出,注意到這邊我們使用了 exec
這個新的指令,只要是對正在運作中的容器下指令,都需要加入 exec
才能執行。
這邊我們退出 nginx 的容器,查看一下容器列表會發現其還在運作:
$ docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64d52ea0... nginx "/doc.. 31 se.. Up 1.. 0.0.0.0:80->80/tcp hungry..
這就回歸到上一個段落所提到的:
只有終止了初始指令所執行的程序,才會使容器進入退出狀態
但這邊我們退出的程序並不是這個容器的初始指令,這個容器的初始指令是 nginx 一開始預設的,所以我們退出 bash 程序並不會造成容器退出。
我們可以再試試看另外一個例子,這邊啟動一個 Ubuntu 的容器:
$ docker container run --interactive --tty --name ubuntu ubuntu # 不換行
root@c4131a4bd1fa:/#
你可能會想問,這邊為什麼不用加 bash 在最後面呢?
這是因為 Ubuntu 這個映像檔本身的初始指令就是 bash,所以我們不需要用別的指令來取代預設的,就會自動啟動 bash 這個程序。
那舉一反三可得知,輸入 exit 後,Ubuntu 容器就會進入退出狀態。
root@c4131a4bd1fa:/# exit
exit
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64d52ea0a1.. nginx "/doc.. 31 se.. Up 2.. 0.0.0.0:80->80/tcp hungry..
c4131a4bd1.. ubu.. "bash" 2 min.. Exited ubuntu
結語
今天介紹了容器的初始指令,也證實了容器進入退出狀態的原因。
明天開始將會進入 Docker 的虛擬網路世界!