Docker 容器化
是什麼?
Docker 是一個容器化平台,把應用程式和所有依賴打包成標準化的 Container。Container 比虛擬機更輕量(共享 OS Kernel),啟動速度以秒計,是現代 CI/CD 和雲端部署的基礎設施。
ℹ️Container vs VM
VM:包含完整 OS,啟動需要分鐘,佔用 GB 級記憶體。Container:共享 Host OS Kernel,啟動只需秒,佔用 MB 級記憶體。Container 不是輕量級 VM,而是一種程序隔離技術。
核心觀念
- Image(映像檔):Container 的藍圖,唯讀的分層檔案系統。由 Dockerfile 定義,可推送到 Registry(如 Docker Hub、GitHub Container Registry)
- Container(容器):Image 的執行實例,有自己的檔案系統、網路、程序空間。可以啟動、停止、刪除
- Dockerfile:定義如何建置 Image 的腳本。每一行指令產生一個新的 Layer
- Docker Compose:用 YAML 定義多個 Container 的組合(如 App + DB + Redis),一鍵啟動整個開發環境
- Multi-stage Build:在 Dockerfile 中用多個 FROM,分離建置環境和執行環境,大幅縮小最終 Image 大小
常見誤區
⚠️常見誤區
- Image 太大:用
node:20作為 base(1GB+),應該用node:20-alpine(~130MB)。最終 Image 不需要包含編譯工具 - 不用 Multi-stage Build:把 build 工具和 source code 留在最終 Image 中,不但肥大還有安全風險
- 用 root 跑容器:Container 內預設用 root 執行,一旦被攻破等於拿到 root 權限。必須建立非 root 用戶
流程/步驟
撰寫 Dockerfile
定義 base image、安裝依賴、複製程式碼、設定啟動命令
Build Image
docker build -t myapp:v1 . 建置映像檔
測試 Container
docker run -p 8080:80 myapp:v1 在本機測試
推送 Registry
docker push 到 Docker Hub 或私有 Registry
Compose 編排
用 docker-compose.yml 定義多容器開發環境
CI/CD 整合
在 Pipeline 中 build、push、deploy Image
流程解讀:Dockerfile 定義 Image 的建置步驟。Build 後在本機測試,確認正常後推送到 Registry。開發環境用 Docker Compose 一鍵啟動多個服務。CI/CD Pipeline 中自動 build 和 push Image。
程式碼範例
C# 版本
# .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 版本
# 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 版本
# 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"]# 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 建置出 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 的倉庫 |