Docker Container 指令:Docker run & Docker exec


Docker Container 對於Docker而言應該算是最常遇到而且最重要的部分之一,所以在這篇文章中,將著眼在Container的操作以及相關的指令說明,例如:docker run、docker exec。首先,先來複習一下:

  • Container是由Image所建立而來,是一個基於Image之上的可讀寫層
  • 一個Image可以建立無限多個Container
  • 每個Container之前都是各別獨立的

推薦閱讀:Docker – 新手入門,快速安裝與基本指令介紹

Docker Container 常見指令操作:Docker run & Docker exec

docker run & docker exec 用法

接下來將就一些常用到的Container操作指令進行說明:

1. 建立 Container

先來複習一下如何啟動Container,這在上一篇文章中已經有介紹過,docker run可以用來建立Container並執行指令,如果本機沒有映像檔,則會自動去pull下載回來執行:

docker run image_name 或
docker run image_id

請注意,如果執行的Container操作不是持續性的,那麼在Container執行完該執行的指令後就會結束,處於Exited (0)狀態

2. docker run 常用參數

docker run這個指令可搭配的參數很多也相對重要,是一個一定要會的指令,以下將列出幾個常見搭配的參數以及實例供大家參考:

–name

替Container取一個別名,由於這個別名是自訂的,因此是一個可用來區分Container的好方法,例如當同一個Image啟動多個Container時,這個指令就特別有用,以下範例就是將Container指定一個名稱「demo」

docker run --name demo tomcat
-i

Keep STDIN open even if not attached,讓標準輸入維持在打開的狀態,通常會和-t一起使用,參數是可以一起合併使用的,因此在寫法上可以是-i -t或者是-it

-t

Allocate a pseudo-tty,替Container配置一個虛擬的終端機,通常會和-i一起使用來綁定標準輸入,這樣這個Container就擁有了標準的輸入輸出能力,例如以busybox為例,執行完以下指令後,可用ls來查看Container內的資訊

[demo@localhost ~]$ docker run -it busybox
/ # ls
bin   dev   etc   home  proc  root  run   sys   tmp   usr   var
/ #
-d

讓Container進入背景執行

docker run -d nginx
-p

利用-p這個參數,可以將主機的Port綁定到Container的Port,格式為host_port:container_port,例如下面的例子就是把主機上的8080連接埠綁定Container的80連接埠

docker run -p 8080:80 tomcat
-v

掛載目錄,其格式為host_volume:container_volume,冒號前面是本機的目錄位置,冒號後面則是Container中的路徑(必需是絕對路徑),例如把本機的「/host/v1」這個目錄掛載到Container的「/container/v2」目錄,這樣會達到共享目錄的效果,也就是說把資料放到「/host/v1」的目錄下時,在Container的「/container/v2」目錄中也能看到這些資料,同樣地,如果把資料複製到Container的「/container/v2」目錄中,在本機的「/host/v1」目錄下也看的到

docker run -v /host/v1:/container/v2 nginx

PS:關於這個參數,其實還有蠻多的變化,這在後續的文章中若有機會再介紹,目前先以最常見的用法為主

–rm

Automatically remove the container when it exits. 意思是說Container執行結束之後會自動被移除,因此Container的Status就不會處在「Exited」的狀態。大家可以自己做個實驗,當有加入–rm參數後有何不同 (可搭配Docker ps -a 查看)

docker run --rm hello-world

3. 常見的 docker exec 用法

執行Container內指令

docker exec這是另一個Docker Container常會用到的指令,就如字面上的意思,它主要的作用是可以進入Container中執行某項命令,但要注意,這個指令要運作正常,Container必需在「活著」的狀態下才行,例如假設Container的狀態是處於「Exited」狀態,那麼執行 docker exec 時會出現錯誤訊息。在下面的範例中,eede6d35b47d是Container ID (也可以換成Container Name)

docker exec eede6d35b47d /bin/ping localhost
進入Container

docker exec可用來進入Container內,然後在Container中執行指令,例如:

[demo@localhost ~]$ docker exec -it 4103ef793ded bash (進入Container)
bash-4.4# ls (進入後可以觀察到 # 字號前的字已有不同,接著就可以直接在Container中執行指令)
bin    dev    etc    home   lib    media  mnt    (以下略)
bash-4.4# exit (輸入exit離開Container 或 熱鍵ctrl+d)
exit
[demo@localhost ~]$

4. docker stop & docker start

通常第一次建立Container時,我們會執行docker run,其狀態會處於「Up」,即啟用狀態,而除了這個之外,我們還可以視需求將Container停止或重啟:

  • docker stop用來停止Container,Container狀態會變更為「Exited (0)」,最簡單的範例就是直接在stop後面加Container Id或Container Name即可,例如:docker stop 4103ef793ded
  • 如果想要重新啟動Container,透過docker start指令即可達成,start後面一樣可接Container Id或Container Name,例如:docker start 4103ef793ded,而Container的狀態會恢復成「Up」

5. 小技巧

簡化Container ID的輸入

在使用Container ID時,可以不用全部都打出來,只要可以讓系統識別就行了,例如下面的指令會把Container ID由「eede6d35b47d」簡化為「eede」

docker exec eede /bin/ping localhost
暫離/恢復Container

如果我們已經進入Container中,要暫時跳離Container內部環境回到Host中,那麼可以直接按ctrl+p後,再按ctrl+q,此時的Container狀態還是會維持在「Up」,可以想成Container已經退到背景去執行了。暫離後,如果要再次回到Container中,那麼可以用docker attach的方式,將Container帶來前景來

[demo@localhost ~]$ docker attach mybash
bash-4.4# (< ==直接進Container中的bash)
docker start直接進Container

重新啟動Container時,可以加直接加-ia進入Container,參數中-a的定義是「Attach STDOUT/STDERR and forward signals」

docker start -ia demobash
start、attach、exec進入Container,再離開後的狀態差別

由前面的範例說明,可以知道要進入Container中的bash,可以使用start、attach、exec任一個指令都可以,但進入Container後若執行ctrl+d或輸入exit離開Container,此時Container狀態卻會有所差異:使用start、attach進入者,離開後Container狀態會轉成「Exited (0)」,而用exec進入的話,則會一樣維持在「Up」狀態

Docker run 與 Docker exec 有何不同?

在使用Docker指令時,有些動作是可以用runexec來達成的,那麼二者有什麼不同呢?其實蠻簡單的,「docker run」適合在沒有Container(容器)可執行的情況下來使用,透過docker run就可以用來建立、啟動一個Container,並執行命令;想反地,docker exec就是針對已存在的Container進行操作,如果Container沒活著,那麼在執行指令時會出現錯誤。

延伸閱讀:
Docker – 新手入門,快速安裝與基本指令介紹
Docker – Dockerfile 指令教學,含範例解說
Docker Compose – 安裝教學、指令用法及官方範例說明