Docker Attach vs Exec

之前在進入 Container 內部時經常使用到 docker attach <ContainerId> 這個命令,不過 Docker 還有提供另一個命令 docker exec
docker exec 顧名思義就是在 container 內部運行一段命令,我們可以在 Host 環境底下直接將命令傳送給 container 內部
交由 container 內部的系統來運行,所以範用性比起 docker attach 更加的廣泛,今天要來比較這兩個命令的區別


Docker Attach

第一個是我們常用的 docker attach,首先我們先安裝 tumx 主要的用途是要開啟兩個 session,也可以開啟兩個 putty 也可以達到同樣的效果
我這邊使用的是 Play with Docker 的環境,可以使用以下命令來進行安裝

apk add tmux

安裝完成後輸入 tmux 就會進入到 tmux 所管理的 Session 了
進入後會看到底下有一條綠色的長條寫著 [0] 0:bash* , 就代表你有正確進入到環境了

tmux

接下來按下快捷鍵 Ctrl + b + c,建立一個新的 Session , 要注意 c 要獨立按下不要按著 Ctrl 這時底下會多出一個 bash 寫著 [0] 0:bash- 1:bash* 後面的星字號 * 代表目前所在的 Session,我們現在位於 Session 1

接下來按下快捷鍵 Ctrl + b + %,將畫面一分為二,左邊為 Session 1 右邊為 Session 2,可以使用 Ctrl + b + 方向鍵 來進行左右 Session 切換 (DCAAttachExec-tmux.png)

都完成後我們在 Session 1 運行起一個 ubuntu container,這邊都是同一台 Host 所以在哪個 Session 執行都可以

docker run -dit ubuntu

之後在 Session 1 使用 docker attach進入 container

docker attach fe3346

進入後輸入 ps 查看有什麼程式正在運行中,可以看到此 container 的 PID 1 正在運行 Bash PID 1 代表 container 主要運行的任務,如果 PID 1 發生異常或停止,Docker 認為此 container 已經完成任務了,會將此 container 停止

root@fe3346a36290:/# ps a
PID TTY          TIME CMD
  1 pts/0    00:00:00 bash
 12 pts/0    00:00:00 ps

接下來使用快捷鍵 Ctrl + b + 方向鍵 切換到 Session 2,並且也使用 docker attach進入 container

docker attach fe3346

輸入命令後會發現怎麼兩個 Session 會同步運行,這是因為 docker attach 的機制,當輸入之後它會附加到container 目前正在運行的 bash
並且兩個 Session 都附加到同一個 bash 上, 所以才會看起來有同步運行的效果,而且因為是附加在 bash 上並且它又是 PID 1
正如剛剛所提到的 PID 1 的程式不可以停止運行,否則 container 會進行關閉,這也就是為什麼之前使用 docker attach 有時需要搭配快捷鍵 Ctrl + b + Ctrl + q 而不是使用 exit 進行退出, 這是因為使用 exit 會將 container 的 bash 關閉,所以整個 container 會進行關閉, 使用快捷鍵 Ctrl + b + Ctrl + q 則不會有這個問題


Docker Exec

接下來測試 docker exec , 也是啟動一個 ubuntu container

docker run -dit ubuntu

這時改用 docker exec 來進入 container 這個命令的意思是請 docker 將命令交給 container 內部執行,也就是剛剛建立的 ubuntu container 並且運行 bash 這個程式

docker exec -it e0a84d bash

進入後輸入 ps a,發現我們剛剛輸入的 exec 命令,已經不是 PID 1了,反而是 PID 9

root@e0a84d79da82:/# ps a                                
  PID TTY      STAT   TIME COMMAND
    1 pts/0    Ss+    0:00 /bin/bash
    9 pts/1    Ss     0:00 bash
   23 pts/1    R+     0:00 ps a

這就是與docker attach最大的不同, docker exec 會另外執行一個 process, 不會附加到原本的 PID 1 上
這樣反而比較安全因為 docker exec 並不會改變 container 原有的行為,隨便進行附加可能會讓 container 產生意外
而且不是PID 1 就代表我們可以使用 exit 進行退出,不會造成 container 停止 最後 docker exec 可以執行任何的命令,並不限於進入 container 這個功能,例如可以使用以下指令 可以輕鬆的列出 distro 資訊,簡單的命令就再也不用在重複進入 container 內部後再進行輸入了

$ docker exec e0a84d cat /etc/os-release       
                              
PRETTY_NAME="Ubuntu 22.04.1 LTS"                                             
NAME="Ubuntu"                                                                
VERSION_ID="22.04"                                                           
VERSION="22.04.1 LTS (Jammy Jellyfish)"                                      
VERSION_CODENAME=jammy                                                       
ID=ubuntu                                                                    
ID_LIKE=debian                                                               
HOME_URL="https://www.ubuntu.com/"                                           
SUPPORT_URL="https://help.ubuntu.com/"                                       
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"                          
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"                                                                       
UBUNTU_CODENAME=jammy   

Summary

今天比較了兩個進入 container 的方法 docker attachdocker exec , 兩個都有各自使用的場合
例如可以利用docker attach的特性,使用完 container 之後想要可以直接輸入 exit 退出同時將 container 關閉,可以不用手動下指令將 container 停止 docker exec 反之更加全面,所以反而都是選擇使用此命令來進入 container 內部

這也是一開使很容易搞混的地方,因為 attach 字面上看起來是附加但卻不是最佳解所以實際上用的不多,反而一個字面上不清楚的 exec 才是最佳解法
之後可以按照自己的需求來選擇要使用那一個命令