目錄

前情提要

昨天介紹了如何和容器內的作業系統透過終端機進行溝通,而今天則會介紹關於容器的初始指令。

也攸關於容器在什麼時候會進入退出狀態。

容器的初始指令

這是昨天的範例:

Interact With Container
  • bash
1
$ docker container run --interactive --tty nginx bash

為什麼在 nginx 後面還要加上 bash 這個指令呢?

我們利用 Docker 提供的 --help 方法來看看,到底後面能夠接受什麼樣的參數呢?

Docker Container Help
  • bash
1
2
3
4
$ 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 這個命令處理器。

接著我們回到容器內部,再次輸入相同的指令,並且離開:

Interact With Container
  • bash
1
2
$ docker container run --interactive --tty nginx bash
[email protected]:/# exit

透過列出容器的指令,我們會發現這個容器竟然進入了退出狀態。

List All Containers
  • bash
1
2
3
4
5
6
$ 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 在背景執行,接著我們試著進入內部:

Into Nginx Container
  • bash
1
2
3
4
5
6
$ 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 正在背景執行,接著我們進入正在運作的容器:

Into Nginx Container
  • bash
1
2
3
4
5
$ docker container exec --interactive --tty 64d52 bash
[email protected]:/# 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
[email protected]:/# exit
exit

我們進入後一樣用了 ls 這個 Linux 指令來查看容器中的檔案,並且輸入 exit 退出,注意到這邊我們使用了 exec 這個新的指令,只要是對正在運作中的容器下指令,都需要加入 exec 才能執行。

這邊我們退出了 nginx 的容器,查看一下容器列表會發現其還在運作:

List Active Container
  • bash
1
2
3
$ 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 的容器:

Running Ubuntu Container
  • bash
1
2
$ docker container run --interactive --tty --name ubuntu ubuntu # 不換行
[email protected]:/#

你可能會想問,這邊為什麼不用加 bash 在最後面呢?

這是因為 Ubuntu 這個映像檔本身的初始指令就是 bash 喲!所以我們不需要用別的指令來取代預設的,就會自動啟動 bash 這個程序。

那舉一反三可得知,我們輸入 exit 後,Ubuntu 容器就會進入退出狀態。

Exited Ubuntu Container
  • bash
1
2
3
4
5
6
7
[email protected]:/# 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 的虛擬網路世界!