Docker Container 容器詳解

深入理解 Docker Container 的概念、生命週期、特性和使用方式


目錄


Container 基本概念

Container 是什麼?

Container = Image 的執行實例
          = 可讀寫的執行環境
          = 隔離的應用程式運行空間

核心特點

  • 從 Image 創建而來
  • 在 Image 上層添加可讀寫層
  • 執行時資料存在可讀寫層
  • 刪除後,寫入層的資料消失

Container 的組成


Image vs Container

對比說明

Image(映像檔)
├─ 唯讀的模板
├─ 靜態的檔案
└─ 可以建立多個 Container

Container(容器)
├─ Image 的執行實例
├─ 動態運行的程序
├─ 可讀寫(但重啟後消失)
└─ 每個 Container 獨立

類比:
Image    = 程式(.exe 檔案)
Container = 執行中的程序

關係圖示

          Image: nginx:latest
        ┌────────┼────────┐
        ↓        ↓        ↓
   Container1 Container2 Container3
   (nginx-1)  (nginx-2)  (nginx-3)

   → 同一個 Image 可以啟動多個 Container
   → 每個 Container 完全獨立
   → Image 保持不變

實際範例

# 1. 查看 Image(靜態)
docker images
# nginx  latest  abc123  100MB

# 2. 從 Image 創建並啟動 Container(動態)
docker run -d --name web1 nginx
docker run -d --name web2 nginx
docker run -d --name web3 nginx

# 3. 查看運行中的 Container
docker ps
# web1, web2, web3 都在運行

# 4. Image 仍然保持不變
docker images
# nginx  latest  abc123  100MB  ← 沒有改變

Container 的生命週期

狀態轉換圖

建立 → 執行 → 暫停 → 停止 → 刪除
 ↓      ↓      ↓      ↓      ↓
Created Running Paused Stopped Removed

docker create   → Created
docker start    → Running
docker pause    → Paused
docker unpause  → Running
docker stop     → Stopped
docker rm       → Removed

完整生命週期流程

1. Created(已建立)
   docker create nginx
   → Container 已建立但未啟動
   → 配置已準備好,但程序未執行

2. Running(執行中)
   docker start <container>
   → 程序正在運行
   → 可以接受請求

3. Paused(暫停)
   docker pause <container>
   → 程序暫停(凍結)
   → 記憶體狀態保留
   → 可以快速恢復

4. Stopped(已停止)
   docker stop <container>
   → 程序已停止
   → Container 仍存在
   → 可以重新啟動

5. Removed(已刪除)
   docker rm <container>
   → Container 完全刪除
   → 寫入層資料消失
   → 無法恢復

常用生命週期指令

# 創建(但不啟動)
docker create --name myapp nginx

# 創建並啟動
docker run -d --name myapp nginx

# 啟動已停止的 Container
docker start myapp

# 重啟 Container
docker restart myapp

# 暫停 Container
docker pause myapp

# 恢復暫停的 Container
docker unpause myapp

# 停止 Container(優雅關閉,10秒後強制)
docker stop myapp

# 強制停止 Container
docker kill myapp

# 刪除已停止的 Container
docker rm myapp

# 強制刪除執行中的 Container
docker rm -f myapp

# 刪除所有已停止的 Container
docker container prune

Container 的特性

主要特性

✅ 輕量級(共享 OS 核心)
   → 啟動快速(秒級)
   → 資源使用少(MB 級別)

✅ 隔離性(互不影響)
   → 獨立的檔案系統
   → 獨立的網路
   → 獨立的程序空間

✅ 可移植性(任何地方執行)
   → 環境一致
   → 跨平台運行

❌ 資料不持久(需要 Volume)
   → Container 刪除後資料消失
   → 需要 Volume 持久化

隔離機制

程序隔離(PID Namespace)
├─ Container 內的 PID 1 是應用程式
├─ 看不到主機的其他程序
└─ 每個 Container 有獨立的程序樹

檔案系統隔離(Mount Namespace)
├─ 獨立的根檔案系統
├─ 看不到主機的檔案
└─ 可以透過 Volume 共享特定目錄

網路隔離(Network Namespace)
├─ 獨立的網路介面
├─ 獨立的 IP 位址
└─ 可以透過 Port 映射對外

使用者隔離(User Namespace)
├─ Container 內的 root 不是主機的 root
└─ 提高安全性

Container 的使用方式

基本執行模式

1. 前景模式(Foreground)

# 前景執行,會佔用終端
docker run nginx

# 查看輸出日誌
# Ctrl+C 停止 Container

# 適用場景:
# - 測試和除錯
# - 需要即時查看日誌

2. 背景模式(Detached)

# 背景執行
docker run -d --name web nginx

# 查看日誌
docker logs web
docker logs -f web  # 持續追蹤

# 適用場景:
# - 生產環境
# - 長時間運行的服務

3. 互動模式(Interactive)

# 互動式執行(進入 Container)
docker run -it ubuntu bash

# 在執行中的 Container 執行指令
docker exec -it web bash

# 適用場景:
# - 除錯
# - 測試指令
# - 查看 Container 內部狀態

Port 映射

# 映射單個 Port
docker run -d -p 8080:80 nginx
# 主機:8080 → Container:80

# 映射多個 Port
docker run -d \
  -p 8080:80 \
  -p 8443:443 \
  nginx

# 隨機映射
docker run -d -P nginx
# Docker 自動分配主機 Port

# 只綁定特定 IP
docker run -d -p 127.0.0.1:8080:80 nginx
# 只有 localhost 可以訪問

環境變數

# 設定單個環境變數
docker run -d -e NODE_ENV=production myapp

# 設定多個環境變數
docker run -d \
  -e NODE_ENV=production \
  -e PORT=3000 \
  -e DB_HOST=mysql \
  myapp

# 從檔案載入環境變數
echo "NODE_ENV=production" > .env
echo "PORT=3000" >> .env
docker run -d --env-file .env myapp

Volume 掛載

# Named Volume
docker run -d -v mydata:/app/data myapp

# Bind Mount
docker run -d -v $(pwd):/app myapp

# 唯讀掛載
docker run -d -v mydata:/app/data:ro myapp

Container 資源管理

CPU 限制

# 限制 CPU 使用量(0.5 = 50%)
docker run -d --cpus="0.5" myapp

# 限制 CPU 份額(相對權重)
docker run -d --cpu-shares=512 myapp

# 指定使用特定 CPU 核心
docker run -d --cpuset-cpus="0,1" myapp

記憶體限制

# 限制記憶體使用
docker run -d -m 512m myapp
docker run -d --memory="1g" myapp

# 限制記憶體 + Swap
docker run -d -m 512m --memory-swap="1g" myapp

# 記憶體預留
docker run -d --memory-reservation="256m" myapp

磁碟 I/O 限制

# 限制讀取速度(bytes per second)
docker run -d --device-read-bps /dev/sda:1mb myapp

# 限制寫入速度
docker run -d --device-write-bps /dev/sda:1mb myapp

# 限制 I/O 操作數(IOPS)
docker run -d --device-read-iops /dev/sda:1000 myapp

查看資源使用情況

# 查看所有 Container 的資源使用
docker stats

# 查看特定 Container
docker stats web1 web2

# 不持續更新(只顯示一次)
docker stats --no-stream

Container 網路連接

網路模式

# Bridge 模式(預設)
docker run -d --network bridge nginx

# Host 模式(使用主機網路)
docker run -d --network host nginx

# None 模式(無網路)
docker run -d --network none nginx

# Container 模式(共享其他 Container 的網路)
docker run -d --network container:web1 nginx

# 自訂網路
docker network create mynet
docker run -d --network mynet --name web nginx

Container 間通訊

# 創建自訂網路
docker network create myapp-net

# 啟動 Database
docker run -d \
  --network myapp-net \
  --name db \
  mysql

# 啟動 App(可以用 'db' 連接資料庫)
docker run -d \
  --network myapp-net \
  --name app \
  -e DB_HOST=db \
  myapp

# 在 app Container 中:
# mysql -h db -u root -p  ← 使用 Container 名稱


實戰範例

範例 1:運行 Web 伺服器

# 啟動 Nginx
docker run -d \
  --name web \
  -p 8080:80 \
  -v $(pwd)/html:/usr/share/nginx/html:ro \
  --restart unless-stopped \
  nginx

# 訪問:http://localhost:8080

範例 2:資料庫容器

# 啟動 MySQL
docker run -d \
  --name mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  -v mysql-data:/var/lib/mysql \
  -p 3306:3306 \
  --restart unless-stopped \
  mysql:8

# 連接資料庫
docker exec -it mysql mysql -uroot -psecret

最佳實踐

1. 使用具名 Container

# ❌ 不好:使用隨機名稱
docker run -d nginx

# ✅ 好:使用有意義的名稱
docker run -d --name web-prod nginx

2. 適當的重啟策略

# no:不自動重啟(預設)
docker run -d --restart=no nginx

# on-failure:失敗時重啟
docker run -d --restart=on-failure nginx

# always:總是重啟
docker run -d --restart=always nginx

# unless-stopped:除非手動停止,否則總是重啟
docker run -d --restart=unless-stopped nginx

3. 健康檢查

# 在 Dockerfile 中定義
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

# 或在執行時定義
docker run -d \
  --health-cmd="curl -f http://localhost/ || exit 1" \
  --health-interval=30s \
  --health-timeout=3s \
  --health-retries=3 \
  nginx

# 查看健康狀態
docker ps
# STATUS: Up 2 minutes (healthy)

4. 清理策略

# 自動刪除停止的 Container
docker run -d --rm --name temp nginx

# 定期清理未使用的 Container
docker container prune

# 清理所有已停止的 Container
docker rm $(docker ps -aq -f status=exited)

5. 日誌管理

# 限制日誌大小
docker run -d \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx

# 使用 json-file driver(預設)
docker run -d --log-driver json-file nginx

# 使用 syslog
docker run -d --log-driver syslog nginx

# 查看日誌
docker logs web
docker logs -f web  # 持續追蹤
docker logs --tail 100 web  # 只看最後 100 行
docker logs --since 10m web  # 只看最近 10 分鐘

6. 安全性設定

# 不要使用 root 使用者
docker run -d --user 1000:1000 myapp

# 唯讀根檔案系統
docker run -d --read-only myapp

# 限制能力(Capabilities)
docker run -d --cap-drop ALL --cap-add NET_BIND_SERVICE nginx

# 使用 Security Options
docker run -d --security-opt no-new-privileges myapp

7. 監控和除錯

# 查看 Container 詳細資訊
docker inspect web

# 查看 Container 內的程序
docker top web

# 查看 Container 的變更
docker diff web

# 進入執行中的 Container
docker exec -it web bash

# 複製檔案
docker cp web:/app/logs/app.log ./
docker cp ./config.json web:/app/

常見問題

Q1: Container 停止後資料會消失嗎?

A: Container 的可讀寫層資料會消失。使用 Volume 可以持久化資料,即使 Container 刪除,資料仍保留。

Q2: 如何進入執行中的 Container?

A: 使用 docker exec -it <container> bashdocker attach <container>。exec 建立新程序,attach 連接主程序。

Q3: Container 和 Image 有什麼關係?

A: Image 是靜態模板,Container 是 Image 的執行實例。一個 Image 可以建立多個獨立的 Container。

Q4: 如何限制 Container 資源?

A: 使用 --cpus 限制 CPU,-m 限制記憶體,--device-read-bps 限制磁碟 I/O。


總結

核心要點

  • Container 是 Image 的執行實例,在 Image 上層添加可讀寫層
  • 生命週期:Created → Running → Paused → Stopped → Removed
  • 支援前景、背景、互動三種執行模式
  • 使用 Volume 持久化資料,使用 Network 連接容器
  • 可限制 CPU、記憶體、磁碟 I/O 資源使用

快速參考

操作 指令 說明
建立並啟動 docker run 一步到位
查看 docker ps 運行中的容器
停止 docker stop 優雅關閉
刪除 docker rm 必須先停止
進入 docker exec -it 互動式操作
日誌 docker logs -f 即時追蹤

建立日期:2025-11-10 最後更新:2025-11-18

🔗相關文章