任務三:容器操作進階¶
開始之前¶
任務目標
在這個任務中,你將學習:
- 理解
docker exec與docker attach的差異與適用場景 - 學會使用
docker logs查看容器日誌 - 掌握
docker stats監控容器資源使用狀況 - 使用
docker top查看容器內的行程 - 使用
docker inspect取得容器詳細資訊 - 學會使用
docker cp在容器與 Host 之間交換檔案 - 理解
export/import與save/load的差異 - 透過實作練習掌握容器操作技巧
進入執行中的容器¶
在容器執行時,我們常常需要進入容器內部執行指令或進行除錯。Docker 提供了兩種方式:docker exec 和 docker attach。雖然這兩個指令都能讓你「進入」容器,但它們的運作方式和適用場景完全不同。
在容器內執行新程式:docker exec¶
docker exec 在執行中的容器內啟動一個新的程式。這是最常用也最安全的進入容器方式。
基本用法:
範例:
# 在容器內執行 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),讓你能看到和互動該程式的輸入輸出。
基本用法:
範例:
重要特性:
- 連接到容器的主程式,看到的是容器啟動時執行的程式輸出
- 如果主程式不是互動式程式(如 nginx、apache),你無法輸入指令
- 如何脫離 attach:
- 按 Ctrl+P 然後 Ctrl+Q:正確的脫離方式,容器繼續執行(啟動時需要給
-it才能正常吃到快捷鍵) - 按 Ctrl+C:發送中斷訊號給主程式,可能導致容器停止
- 若主程式是 shell,輸入
exit或按 Ctrl+D:結束 shell,容器會停止
- 按 Ctrl+P 然後 Ctrl+Q:正確的脫離方式,容器繼續執行(啟動時需要給
實際應用場景:
# 查看應用程式的即時輸出
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 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
# 只顯示特定容器
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 top¶
docker top 顯示容器內執行中的程式,類似 Linux 的 top 或 ps 指令。
基本用法:
範例:
輸出範例:
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
實際應用:
取得容器完整資訊:docker inspect¶
docker inspect 顯示容器的詳細設定與狀態資訊,輸出為 JSON 格式。
基本用法:
範例:
# 查看容器的完整資訊
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目錄內容到bardocker cp foo container:/bar:複製foo目錄本身到bar,結果為bar/foo
最佳實踐:
- 開發環境:使用 Volume 掛載取代頻繁的
docker cp - 生產環境:避免使用
docker cp,改用 Volume 或重新建立容器 - 暫時性需求:適合用於除錯、備份、一次性的檔案傳輸
容器與映像檔的匯出匯入¶
有時候我們需要將容器或映像檔打包成檔案,以便在沒有網路的環境中傳輸,或是備份重要的容器狀態。Docker 提供了兩組指令:export/import 和 save/load,它們看起來相似,但用途和效果完全不同。
匯出容器為映像檔:export/import¶
docker export 將容器的檔案系統匯出為 tar 檔案,docker import 將 tar 檔案匯入為映像檔。
匯出容器:docker export¶
將容器的完整檔案系統打包成 tar 檔案。
範例:
# 匯出容器為 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 檔案匯入為新的映像檔。
範例:
# 從 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 -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 -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 容器,並使用各種工具監控它的狀態。
步驟:
-
啟動 nginx 容器
-
查看容器日誌
開啟瀏覽器前往
http://localhost:8080,然後觀察終端機的日誌輸出。你會看到存取記錄出現。按 Ctrl+C 停止追蹤。 -
監控資源使用狀況
觀察 CPU、記憶體、網路流量等資訊。按 Ctrl+C 停止監控。
-
查看容器內的程式
你會看到 nginx 的 master process 和 worker process。
-
取得容器詳細資訊
-
進入容器查看設定
-
清理容器
練習二:檔案操作¶
在這個練習中,我們會練習在容器與 Host 之間複製檔案。
步驟:
-
啟動 nginx 容器
-
建立一個自訂的 HTML 檔案
在 Host 上建立一個 HTML 檔案:
-
將檔案複製到容器內
-
驗證變更
開啟瀏覽器前往
http://localhost:8080,你應該會看到「Hello from Docker!」。 -
從容器複製檔案到 Host
-
建立容器的備份
-
清理
延伸挑戰:
試著完成以下任務:
- 啟動一個 Ubuntu 容器,在容器內建立一個文字檔案,然後使用
docker cp將它複製出來 - 使用
docker stats --no-stream建立一個簡單的監控腳本,每 5 秒記錄一次容器的資源使用狀況 - 使用
docker save和docker load備份並還原一個映像檔
任務結束¶
完成!
恭喜你完成了這個任務!現在你已經學會:
- 理解
docker exec與docker attach的差異與適用場景 - 學會使用
docker logs查看容器日誌 - 掌握
docker stats監控容器資源使用狀況 - 使用
docker top查看容器內的程式 - 使用
docker inspect取得容器詳細資訊 - 學會使用
docker cp在容器與 Host 之間交換檔案 - 理解
export/import與save/load的差異 - 透過實作練習掌握容器操作技巧
你現在已經掌握了容器操作的進階技巧!這些技能在日常維運和除錯時非常實用。在下一個任務中,我們將學習如何建立自己的 Docker 映像檔,讓你能夠打包和分發自己的應用程式。