Docker 容器化

是什麼?

Docker 是一個容器化平台,把應用程式和所有依賴打包成標準化的 Container。Container 比虛擬機更輕量(共享 OS Kernel),啟動速度以秒計,是現代 CI/CD 和雲端部署的基礎設施。

ℹ️Container vs VM

VM:包含完整 OS,啟動需要分鐘,佔用 GB 級記憶體。Container:共享 Host OS Kernel,啟動只需秒,佔用 MB 級記憶體。Container 不是輕量級 VM,而是一種程序隔離技術。

核心觀念

常見誤區

⚠️常見誤區

  • Image 太大:用 node:20 作為 base(1GB+),應該用 node:20-alpine(~130MB)。最終 Image 不需要包含編譯工具
  • 不用 Multi-stage Build:把 build 工具和 source code 留在最終 Image 中,不但肥大還有安全風險
  • 用 root 跑容器:Container 內預設用 root 執行,一旦被攻破等於拿到 root 權限。必須建立非 root 用戶

流程/步驟

1

撰寫 Dockerfile

定義 base image、安裝依賴、複製程式碼、設定啟動命令

2

Build Image

docker build -t myapp:v1 . 建置映像檔

3

測試 Container

docker run -p 8080:80 myapp:v1 在本機測試

4

推送 Registry

docker push 到 Docker Hub 或私有 Registry

5

Compose 編排

用 docker-compose.yml 定義多容器開發環境

6

CI/CD 整合

在 Pipeline 中 build、push、deploy Image

流程解讀:Dockerfile 定義 Image 的建置步驟。Build 後在本機測試,確認正常後推送到 Registry。開發環境用 Docker Compose 一鍵啟動多個服務。CI/CD Pipeline 中自動 build 和 push Image。

程式碼範例

C# 版本

dockerfile
# .NET Multi-stage Dockerfile
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
 
# Stage 2: Runtime(最終 Image 只有 runtime,不含 SDK)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
 
# 建立非 root 用戶
RUN adduser --disabled-password --gecos "" appuser
USER appuser
 
COPY --from=build /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.dll"]

TypeScript 版本

dockerfile
# Node.js Multi-stage Dockerfile
# Stage 1: Build
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
RUN npm run build
 
# Stage 2: Runtime
FROM node:20-alpine AS runtime
WORKDIR /app
 
# 非 root 用戶
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
 
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY package*.json .
 
EXPOSE 3000
CMD ["node", "dist/index.js"]

Python 版本

dockerfile
# Python Multi-stage Dockerfile
FROM python:3.12-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/deps -r requirements.txt
 
FROM python:3.12-slim AS runtime
WORKDIR /app
 
RUN useradd --create-home appuser
USER appuser
 
COPY --from=build /deps /home/appuser/.local/lib/python3.12/site-packages
COPY . .
 
EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
yaml
# docker-compose.yml — 開發環境
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
    depends_on:
      - db
      - redis
 
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
 
  redis:
    image: redis:7-alpine
 
volumes:
  pgdata:

架構圖/概念圖

Dockerfile
docker build
Docker Image (Layers)
docker push
Container Registry
docker run
Container (Dev)
Container (Staging)
Container (Prod)

Dockerfile 建置出 Image,推送到 Registry 後,任何環境都能從 Registry 拉取同一個 Image 建立 Container。Dev、Staging、Prod 跑的是同一個 Image,確保環境一致性。

實戰補充

Q: Image 太大怎麼瘦身?

A: (1) 用 Alpine 基底(node:20-alpine)。(2) 用 Multi-stage Build,最終 Image 不含 SDK 和 Build 工具。(3) .dockerignore 排除不需要的檔案。(4) 合併 RUN 指令減少 Layer 數量。

Q: Docker Compose 和 Kubernetes 的關係?

A: Docker Compose 適合本機開發和簡單部署(單機多容器)。Kubernetes 適合生產環境的大規模容器編排(多機、自動擴縮、滾動更新)。開發時用 Compose,上線用 K8s。

Q: Volume 和 Bind Mount 有什麼區別?

A: Volume-v mydata:/data):Docker 管理的持久化儲存,適合資料庫等需要持久化的場景。Bind Mount-v ./src:/app/src):直接掛載 Host 目錄,適合開發時即時同步程式碼。

理解測驗

🤔 Container 和 VM 的核心差異是什麼?

🤔 Multi-stage Build 的主要好處是什麼?

🤔 為什麼 Container 內不應該用 root 執行?

重點整理

💡一句話記住

Docker = 把應用和環境打包成標準貨櫃,走到哪都能跑。 口訣:「Dockerfile 定義、Image 打包、Container 執行」

| 概念 | 說明 | |------|------| | Image | 唯讀藍圖,由 Dockerfile 建置 | | Container | Image 的執行實例 | | Multi-stage | 分離 Build 和 Runtime,縮小 Image | | Compose | YAML 定義多容器開發環境 | | Registry | 存放和分發 Image 的倉庫 |

你可能也想看

Pipeline 中的測試策略部署策略

按 ← → 鍵切換課程