常用指令與清理流程#

到目前為止用到的 docker run 只是冰山一角。日常操作容器(Container)時,最常使用的還有 psexeclogsinspectrm 等指令。本章整理這幾個指令的用法,並提供一份標準的實驗清理流程。

docker ps:列出容器#

docker ps 列出目前正在執行的容器:

docker ps

預期輸出(具體值依環境而異):欄位包含 CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES

常用選項:

  • -a / --all:包含已停止的容器
  • -q / --quiet:只輸出容器 ID(適合 pipe 給其他指令)
  • -s / --size:顯示容器佔用的磁碟空間
  • --filter:依條件過濾,例如 --filter status=exited
  • --format:自訂輸出格式(Go template)

例如只想看停止的容器 ID:

docker ps -aq --filter status=exited

docker exec:在執行中的容器內執行指令#

docker exec 在已執行的容器內 fork 一個新行程(Process),不影響原本的 PID 1:

# 進入互動式 shell
docker exec -it mybox sh

# 執行單一指令
docker exec mybox ls /
docker exec mybox cat /etc/hostname

注意事項:

  • exec 出來的行程在容器的 PID Namespace 內有獨立的 PID,但不是 PID 1
  • 該行程結束不會影響容器存活
  • 如果容器內沒有指定 shell(例如 distroless 映像),exec shell 會失敗

docker exec 是除錯利器:可以在不重啟容器的情況下進去看 log、檔案、行程狀態。但它無法替代「正確的 PID 1 設計」——如果 PID 1 寫得不好,再多 exec 也救不了訊號處理。

docker logs:查看容器 STDOUT/STDERR#

容器的 PID 1 寫到 STDOUT 與 STDERR 的內容,會被 Docker daemon 收集並儲存(預設使用 json-file driver)。docker logs 讀取這些紀錄:

# 看完整 log
docker logs mybox

# 持續追蹤新輸出(類似 tail -f)
docker logs -f mybox

# 只看最近 100 行
docker logs --tail 100 mybox

# 加上時間戳
docker logs -t mybox

# 限定時間區間
docker logs --since 10m --until 1m mybox

注意事項:

  • docker logs 只看得到 PID 1 的 STDIO,不包含應用寫入檔案的 log
  • 因此容器化的應用最佳實踐是「把 log 寫到 STDOUT/STDERR」,而不是檔案
  • 大量 log 會吃磁碟,正式環境建議搭配 log rotation 或外部 log driver

docker inspect:查看容器/映像的完整中繼資料#

docker inspect 輸出 JSON 格式的詳細資訊:

# 看容器
docker inspect mybox

# 看映像
docker inspect alpine

# 只取特定欄位(用 Go template)
docker inspect --format '{{.State.Status}}' mybox
docker inspect --format '{{.NetworkSettings.IPAddress}}' mybox
docker inspect --format '{{.State.Pid}}' mybox

可以從 inspect 看到的常用資訊:

  • 容器狀態:State.StatusState.ExitCodeState.Pid(host 視角下的 PID 1)
  • 網路設定:NetworkSettings.IPAddressNetworkSettings.Ports
  • 掛載:Mounts
  • 啟動參數:Config.CmdConfig.EntrypointConfig.Env
  • cgroups 與 namespace 路徑(部分版本)

State.Pid 特別值得注意:它就是上一章「在 host 殺掉 ash」實驗裡需要的 PID。

docker rm:移除容器#

停止的容器並不會自動消失,必須手動 rm

# 移除單一容器
docker rm mybox

# 強制移除(即使還在執行也直接 SIGKILL 後刪除)
docker rm -f mybox

# 一次移除多個
docker rm c1 c2 c3

如果想啟動容器時就指定「結束自動刪除」,加 --rm

docker run -it --rm alpine

docker stop / kill / start / restart#

容器生命週期相關的其他指令:

# 優雅停止(先 SIGTERM,10 秒後 SIGKILL)
docker stop mybox

# 自訂等待時間
docker stop -t 30 mybox

# 直接 SIGKILL
docker kill mybox

# 啟動已停止的容器
docker start mybox

# 重啟(= stop + start)
docker restart mybox

docker stop 會先送 SIGTERM 給 PID 1,給應用機會做 graceful shutdown。如果 PID 1 沒有正確處理 SIGTERM(常見於 shell wrapper 裡跑應用的情況),就會等到 timeout 後被 SIGKILL,造成資料未刷盤等問題。

標準實驗清理流程#

跑完一輪實驗後,建議的清理順序:

# 1. 看看現在有哪些容器
docker ps -a

# 2. 停止所有執行中的容器
docker stop $(docker ps -q)

# 3. 移除所有已停止的容器
docker container prune -f

# 4. 移除沒被任何容器使用的映像
docker image prune -f

# 5. 移除沒被使用的網路
docker network prune -f

# 6. 移除沒被使用的 volume(小心:會刪資料!)
docker volume prune -f

如果想一次清光(謹慎使用):

docker system prune -af --volumes

預期輸出(具體值依環境而異):每個 prune 指令會列出刪除的物件清單與釋放的磁碟空間總計。

用一張表整理生命週期#

狀態觸發指令實際發生的事
createddocker createnamespaces / cgroups 已建好,但 PID 1 尚未啟動
runningdocker start / docker runPID 1 執行中
pauseddocker pausefreezer cgroup 凍結所有行程
exitedPID 1 結束 / docker stopnamespace 銷毀,rootfs 仍保留
removeddocker rmrootfs 與 metadata 一併刪除

小結#

run 是入口、ps 是儀表板、exec 是除錯、logs 是觀測、inspect 是內視鏡、rmprune 是收尾。掌握這六個指令後,日常操作 Docker 的需求基本都能應付。後續章節將深入 image、namespaces、行程訊號、網路等主題,這些 CLI 會頻繁登場。

延伸閱讀#