跳轉到

任務三:容器操作進階

開始之前

任務目標

在這個任務中,你將學習:

  • 理解 docker execdocker attach 的差異與適用場景
  • 學會使用 docker logs 查看容器日誌
  • 掌握 docker stats 監控容器資源使用狀況
  • 使用 docker top 查看容器內的行程
  • 使用 docker inspect 取得容器詳細資訊
  • 學會使用 docker cp 在容器與 Host 之間交換檔案
  • 理解 export/importsave/load 的差異
  • 透過實作練習掌握容器操作技巧

進入執行中的容器

在容器執行時,我們常常需要進入容器內部執行指令或進行除錯。Docker 提供了兩種方式:docker execdocker attach。雖然這兩個指令都能讓你「進入」容器,但它們的運作方式和適用場景完全不同。

在容器內執行新程式:docker exec

docker exec 在執行中的容器內啟動一個新的程式。這是最常用也最安全的進入容器方式。

基本用法:

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

範例:

# 在容器內執行 bash shell(互動模式)
docker exec -it my-container bash

# 執行單一指令並取得結果
docker exec my-container ls /app

# 以特定使用者身分執行指令
docker exec -u root my-container apt-get update

# 在容器內執行指令並查看環境變數
docker exec my-container env

常用參數:

  • -i:保持標準輸入開啟
  • -t:分配偽終端機
  • -u:指定執行指令的使用者
  • -w:指定工作目錄

重要特性:

  • 啟動的是新的程式,不會影響容器的主程式
  • 離開時(如輸入 exit)只會結束這個新程式,容器會繼續執行
  • 可以同時開啟多個 docker exec 連線

實際應用場景:

# 除錯:進入容器查看檔案
docker exec -it web-server bash
ls /var/log
cat /etc/nginx/nginx.conf

# 執行維護指令
docker exec db-container pg_dump mydb > backup.sql

# 查看即時日誌
docker exec web-server tail -f /var/log/access.log

附加到容器的主程式:docker attach

docker attach 附加到容器的主程式(PID 1),讓你能看到和互動該程式的輸入輸出。

基本用法:

docker attach [OPTIONS] CONTAINER

範例:

# 附加到容器的主程式
docker attach my-container

重要特性:

  • 連接到容器的主程式,看到的是容器啟動時執行的程式輸出
  • 如果主程式不是互動式程式(如 nginx、apache),你無法輸入指令
  • 如何脫離 attach:
    • Ctrl+P 然後 Ctrl+Q:正確的脫離方式,容器繼續執行(啟動時需要給 -it 才能正常吃到快捷鍵)
    • Ctrl+C:發送中斷訊號給主程式,可能導致容器停止
    • 若主程式是 shell,輸入 exit 或按 Ctrl+D:結束 shell,容器會停止

實際應用場景:

# 查看應用程式的即時輸出
docker run -d -p 8080:80 --name web nginx
docker attach web  # 查看 nginx 的標準輸出

# 進入互動式容器(如果主程式是 shell)
docker run -d -it --name ubuntu-test ubuntu bash
docker attach ubuntu-test  # 進入這個 bash shell

exec vs attach 比較

比較項目 docker exec docker attach
作用方式 在容器內啟動新程式 附加到容器的主程式(PID 1)
離開後影響 只結束新程式,容器繼續執行 若結束主程式,容器會停止
多人使用 可同時多個 exec 連線 所有 attach 共享同一個輸入輸出
互動性 任何時候都能互動 取決於主程式是否支援互動
適用場景 除錯、執行維護指令、查看檔案 查看應用程式即時輸出、進入互動式容器
建議使用度 日常推薦 特殊場景使用

最佳實踐:

  • 日常操作使用 docker exec:更安全、更靈活、不會意外停止容器
  • 查看應用輸出使用 docker logs:比 attach 更方便
  • 只在特殊情況使用 docker attach:例如需要向主程式傳送訊號時

查看容器狀態

了解容器的執行狀態是維運容器的重要技能。Docker 提供了多個工具讓你從不同角度監控容器。

查看容器日誌:docker logs

docker logs 取得容器的標準輸出(stdout)和標準錯誤(stderr)日誌。

基本用法:

docker logs [OPTIONS] CONTAINER

常用參數:

# 查看容器的所有日誌
docker logs my-container

# 即時追蹤日誌(類似 tail -f)
docker logs -f my-container

# 只顯示最後 100 行
docker logs --tail 100 my-container

# 顯示時間戳記
docker logs -t my-container

# 顯示最近 10 分鐘的日誌
docker logs --since 10m my-container

# 組合使用:即時追蹤最後 50 行並顯示時間
docker logs -f --tail 50 -t my-container

實際應用:

# 除錯 Web 伺服器
docker logs -f --tail 100 nginx-server

# 查看應用程式啟動時的錯誤
docker logs my-app | grep ERROR

# 查看特定時間範圍的日誌
docker logs --since "2024-01-01T00:00:00" --until "2024-01-02T00:00:00" my-app

注意事項:

  • 只顯示容器主程式(PID 1)的輸出
  • 如果應用程式將日誌寫入檔案而非 stdout,docker logs 看不到
  • 日誌會佔用磁碟空間,建議設定 log rotation

監控資源使用狀況:docker stats

docker stats 即時顯示容器的資源使用統計,包含 CPU、記憶體、網路和磁碟 I/O。

基本用法:

docker stats [OPTIONS] [CONTAINER...]

範例:

# 顯示所有執行中容器的資源使用狀況
docker stats

# 只顯示特定容器
docker stats my-container

# 不使用串流模式,只顯示一次
docker stats --no-stream

# 只顯示容器 ID 和名稱
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

輸出欄位說明:

CONTAINER ID   NAME          CPU %    MEM USAGE / LIMIT     MEM %    NET I/O          BLOCK I/O
a1b2c3d4e5f6   web-server    0.25%    50MiB / 2GiB         2.44%    1.2kB / 800B     0B / 0B
  • CPU %:CPU 使用率
  • MEM USAGE / LIMIT:記憶體使用量 / 可用記憶體上限
  • MEM %:記憶體使用率百分比
  • NET I/O:網路傳入 / 傳出流量
  • BLOCK I/O:磁碟讀取 / 寫入量

實際應用:

# 取得當下容器的資源使用統計
docker stats --no-stream my-app

# 持續監控特定容器的資源使用
docker stats web-server db-server

查看容器內的程式:docker top

docker top 顯示容器內執行中的程式,類似 Linux 的 topps 指令。

基本用法:

docker top CONTAINER [ps OPTIONS]

範例:

# 查看容器內的所有程式
docker top my-container

# 只顯示特定欄位
docker top my-container -o pid,user

輸出範例:

PID                 USER                TIME                COMMAND
4237                root                0:00                nginx: master process nginx -g daemon off;
4282                dockremap           0:00                nginx: worker process
4283                dockremap           0:00                nginx: worker process
4284                dockremap           0:00                nginx: worker process
4285                dockremap           0:00                nginx: worker process
4286                dockremap           0:00                nginx: worker process
4287                dockremap           0:00                nginx: worker process
4288                dockremap           0:00                nginx: worker process
4289                dockremap           0:00                nginx: worker process
4290                dockremap           0:00                nginx: worker process
4291                dockremap           0:00                nginx: worker process

實際應用:

# 檢查 Web 伺服器的 worker 數量
docker top nginx-server

# 查看資料庫容器的行程狀態
docker top postgres-db

取得容器完整資訊:docker inspect

docker inspect 顯示容器的詳細設定與狀態資訊,輸出為 JSON 格式。

基本用法:

docker inspect [OPTIONS] CONTAINER [CONTAINER...]

範例:

# 查看容器的完整資訊
docker inspect my-container

# 使用 --format 提取特定欄位
docker inspect --format='{{.State.Status}}' my-container

# 取得容器的 IP 位址
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container

# 查看容器的環境變數
docker inspect --format='{{.Config.Env}}' my-container

# 取得容器的掛載點資訊
docker inspect --format='{{json .Mounts}}' my-container

實際應用:

# 除錯網路問題:查看容器的網路設定
docker inspect --format='{{json .NetworkSettings}}' my-container

# 查看容器的重啟策略
docker inspect --format='{{.HostConfig.RestartPolicy}}' my-container

# 取得容器建立時使用的映像檔
docker inspect --format='{{.Config.Image}}' my-container

# 查看容器的資源限制
docker inspect --format='Memory: {{.HostConfig.Memory}}, CPU: {{.HostConfig.CpuShares}}' my-container

容器與 Host 之間的檔案交換

有時候我們需要在容器和 Host 之間複製檔案,例如取出容器內的日誌檔案,或將設定檔傳入容器。docker cp 讓你能輕鬆完成這個任務。

複製檔案:docker cp

docker cp 在容器與 Host 之間複製檔案或目錄,不需要容器正在執行

基本用法:

# 從容器複製到 Host
docker cp CONTAINER:SRC_PATH DEST_PATH

# 從 Host 複製到容器
docker cp SRC_PATH CONTAINER:DEST_PATH

從容器複製到 Host

將容器內的檔案或目錄複製到 Host 上。

範例:

# 複製容器內的單一檔案
docker cp my-container:/app/config.json ./config.json

# 複製整個目錄
docker cp my-container:/var/log/nginx ./nginx-logs

# 複製到當前目錄
docker cp my-container:/app/output.txt .

# 複製時保留目錄結構
docker cp my-container:/etc/nginx/conf.d ./backup/

實際應用:

# 備份容器內的資料庫
docker cp db-container:/var/lib/postgresql ./db-backup

# 取出應用程式產生的報告
docker cp app-container:/app/reports ./reports

# 除錯:取出容器內的日誌檔案
docker cp my-app:/var/log/app.log ./app.log

從 Host 複製到容器

將 Host 上的檔案或目錄複製到容器內。

範例:

# 複製設定檔到容器
docker cp ./config.json my-container:/app/config.json

# 複製整個目錄到容器
docker cp ./html my-container:/usr/share/nginx/

# 更新容器內的憑證檔案
docker cp ./ssl/cert.pem my-container:/etc/ssl/certs/

# 複製腳本到容器並執行
docker cp ./init.sh my-container:/tmp/init.sh
docker exec my-container bash /tmp/init.sh

實際應用:

# 熱更新設定檔
docker cp ./nginx.conf web-server:/etc/nginx/nginx.conf
docker exec web-server nginx -s reload

# 傳入測試資料
docker cp ./test-data.csv app-container:/app/data/

# 修復問題:替換損壞的檔案
docker cp ./fixed-binary my-container:/usr/local/bin/app

注意事項:

  • 使用 docker cp 不需要容器正在執行(但建議容器執行中以避免檔案鎖定問題)
  • 如果目標路徑已存在,會覆蓋檔案
  • 複製目錄時,尾隨斜線與點時 /. 會影響行為:
    • docker cp foo/. container:/bar:複製 foo 目錄內容bar
    • docker cp foo container:/bar:複製 foo 目錄本身到 bar,結果為 bar/foo

最佳實踐:

  • 開發環境:使用 Volume 掛載取代頻繁的 docker cp
  • 生產環境:避免使用 docker cp,改用 Volume 或重新建立容器
  • 暫時性需求:適合用於除錯、備份、一次性的檔案傳輸

容器與映像檔的匯出匯入

有時候我們需要將容器或映像檔打包成檔案,以便在沒有網路的環境中傳輸,或是備份重要的容器狀態。Docker 提供了兩組指令:export/importsave/load,它們看起來相似,但用途和效果完全不同。

匯出容器為映像檔:export/import

docker export 將容器的檔案系統匯出為 tar 檔案,docker import 將 tar 檔案匯入為映像檔。

匯出容器:docker export

將容器的完整檔案系統打包成 tar 檔案。

docker export [OPTIONS] CONTAINER

範例:

# 匯出容器為 tar 檔案
docker export my-container > container-backup.tar

# 使用 -o 參數指定輸出檔案
docker export -o container-backup.tar my-container

# 壓縮匯出結果以節省空間
docker export my-container | gzip > container-backup.tar.gz

匯入為映像檔:docker import

將 tar 檔案匯入為新的映像檔。

docker import [OPTIONS] file|URL [REPOSITORY[:TAG]]

範例:

# 從 tar 檔案匯入為映像檔
docker import container-backup.tar my-image:backup

# 從壓縮檔匯入
gunzip -c container-backup.tar.gz | docker import - my-image:backup

# 從網路 URL 匯入
docker import https://example.com/backup.tar my-image:v1

# 匯入時設定啟動指令
docker import --change 'CMD ["nginx", "-g", "daemon off;"]' backup.tar my-nginx:v1

重要特性:

  • 匯出的是容器的完整檔案系統快照
  • 不包含 volume 掛載的資料
  • 不保留映像檔的 layer history
  • 不保留映像檔的 meta 資訊例如(command, env 等等)
  • 適合用於快速備份容器的當前狀態

save/load:匯出映像檔

docker save 將映像檔(包含所有 layer 和 metadata)匯出為 tar 檔案,docker load 從 tar 檔案載入映像檔。

匯出映像檔:docker save

將映像檔完整匯出,包含所有 layer、tag 和歷史紀錄。

docker save [OPTIONS] IMAGE [IMAGE...]

範例:

# 匯出單一映像檔
docker save -o nginx-backup.tar nginx:latest

# 匯出多個映像檔到同一個檔案
docker save -o images-backup.tar nginx:latest redis:latest

# 匯出並壓縮
docker save nginx:latest | gzip > nginx-backup.tar.gz

# 匯出映像檔的所有 tag
docker save -o nginx-all.tar nginx

載入映像檔:docker load

從 tar 檔案載入映像檔。

docker load [OPTIONS]

範例:

# 從檔案載入映像檔
docker load -i nginx-backup.tar

# 從標準輸入載入
docker load < nginx-backup.tar

# 從壓縮檔載入
gunzip -c nginx-backup.tar.gz | docker load

重要特性:

  • 保留映像檔的完整 layer history
  • 保留所有 tag 和 metadata
  • 載入後映像檔與原本的完全相同
  • 適合用於映像檔的備份、離線傳輸、版本控制

export/import vs save/load 比較

比較項目 export/import save/load
作用對象 容器(Container) 映像檔(Image)
保留 layer history ❌ 否,壓平為單層 ✅ 是,保留所有 layer
保留 metadata ❌ 否,需重新設定 ✅ 是,完整保留
檔案大小 通常較小(只有一層) 較大(包含所有 layer)
載入速度 較快 較慢(需重建 layer)
適用場景 容器狀態備份、快速遷移 映像檔分發、離線部署、版本備份

使用建議:

使用 export/import:

  • 你想保存容器的當前狀態(包含所有執行時的變更)
  • 需要將容器「壓平」為單一層以減小檔案大小
  • 不在乎 layer history 或 build 快取

使用 save/load:

  • 你想備份或傳輸映像檔本身
  • 需要在沒有網路的環境中部署映像檔
  • 想保留映像檔的 layer history 以便快取重用
  • 需要傳輸自行建立的映像檔到其他伺服器

實際應用範例:

# 情境 1:備份容器的當前狀態
docker export my-container > container-state.tar
docker import container-state.tar my-container:backup

# 情境 2:離線傳輸映像檔到另一台機器
# 在有網路的機器上:
docker pull nginx:latest
docker save -o nginx.tar nginx:latest
# 透過 USB 或其他方式傳輸 nginx.tar 到離線機器
# 在離線機器上:
docker load -i nginx.tar

# 情境 3:備份自製映像檔
docker build -t my-app:v1 .
docker save -o my-app-v1.tar my-app:v1
# 保存到備份儲存空間

# 情境 4:快速複製容器到另一台機器
docker export running-app > app-state.tar
scp app-state.tar user@remote-server:/tmp/
# 在遠端機器上:
docker import /tmp/app-state.tar my-app:migrated
docker run -d my-app:migrated

實作練習

現在讓我們透過實作練習來鞏固學到的容器操作技巧。

練習一:容器狀態監控

在這個練習中,我們會啟動一個 nginx 容器,並使用各種工具監控它的狀態。

步驟:

  1. 啟動 nginx 容器

    docker run -d -p 8080:80 --name monitor-demo nginx
    
  2. 查看容器日誌

    # 查看所有日誌
    docker logs monitor-demo
    
    # 即時追蹤日誌
    docker logs -f monitor-demo
    

    開啟瀏覽器前往 http://localhost:8080,然後觀察終端機的日誌輸出。你會看到存取記錄出現。按 Ctrl+C 停止追蹤。

  3. 監控資源使用狀況

    # 查看資源使用統計
    docker stats monitor-demo
    

    觀察 CPU、記憶體、網路流量等資訊。按 Ctrl+C 停止監控。

  4. 查看容器內的程式

    # 查看執行中的程式
    docker top monitor-demo
    

    你會看到 nginx 的 master process 和 worker process。

  5. 取得容器詳細資訊

    # 查看容器的 IP 位址
    docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' monitor-demo
    
    # 查看容器的狀態
    docker inspect --format='{{.State.Status}}' monitor-demo
    
    # 查看容器使用的映像檔
    docker inspect --format='{{.Config.Image}}' monitor-demo
    
  6. 進入容器查看設定

    # 使用 exec 進入容器
    docker exec -it monitor-demo bash
    
    # 在容器內執行指令
    cat /etc/nginx/nginx.conf
    ls /usr/share/nginx/html
    exit
    
  7. 清理容器

    docker stop monitor-demo
    docker rm monitor-demo
    

練習二:檔案操作

在這個練習中,我們會練習在容器與 Host 之間複製檔案。

步驟:

  1. 啟動 nginx 容器

    docker run -d -p 8080:80 --name file-demo nginx
    
  2. 建立一個自訂的 HTML 檔案

    在 Host 上建立一個 HTML 檔案:

    echo '<h1>Hello from Docker!</h1>' > index.html
    
  3. 將檔案複製到容器內

    docker cp index.html file-demo:/usr/share/nginx/html/index.html
    
  4. 驗證變更

    開啟瀏覽器前往 http://localhost:8080,你應該會看到「Hello from Docker!」。

  5. 從容器複製檔案到 Host

    # 複製 nginx 的預設設定檔
    docker cp file-demo:/etc/nginx/nginx.conf ./nginx.conf
    
    # 查看設定檔內容
    cat nginx.conf
    
  6. 建立容器的備份

    # 使用 export 匯出容器
    docker export file-demo > file-demo-backup.tar
    
    # 查看 tar 檔案大小
    ls -lh file-demo-backup.tar
    
  7. 清理

    docker stop file-demo
    docker rm file-demo
    rm index.html nginx.conf file-demo-backup.tar
    

延伸挑戰:

試著完成以下任務:

  1. 啟動一個 Ubuntu 容器,在容器內建立一個文字檔案,然後使用 docker cp 將它複製出來
  2. 使用 docker stats --no-stream 建立一個簡單的監控腳本,每 5 秒記錄一次容器的資源使用狀況
  3. 使用 docker savedocker load 備份並還原一個映像檔

任務結束

完成!

恭喜你完成了這個任務!現在你已經學會:

  • 理解 docker execdocker attach 的差異與適用場景
  • 學會使用 docker logs 查看容器日誌
  • 掌握 docker stats 監控容器資源使用狀況
  • 使用 docker top 查看容器內的程式
  • 使用 docker inspect 取得容器詳細資訊
  • 學會使用 docker cp 在容器與 Host 之間交換檔案
  • 理解 export/importsave/load 的差異
  • 透過實作練習掌握容器操作技巧

你現在已經掌握了容器操作的進階技巧!這些技能在日常維運和除錯時非常實用。在下一個任務中,我們將學習如何建立自己的 Docker 映像檔,讓你能夠打包和分發自己的應用程式。