本文 AI 產出,尚未審核

FastAPI 部署與架構:Docker 化 FastAPI

簡介

在現代的微服務與雲端環境中,容器化已成為部署應用程式的事實標準。透過 Docker,我們可以把 FastAPI 應用與其所有相依套件、執行環境封裝成一個可移植、可重現的映像檔 (image)。這樣不僅減少「在我機器上可以跑」的問題,還能在 CI/CD 流程、Kubernetes 叢集或雲端平台上快速擴展。

FastAPI 本身以高效能、易於開發著稱,但若缺乏適當的部署方式,仍可能在生產環境中遇到 環境不一致資源浪費部署失敗 等痛點。本文將從概念說明、實作範例,到常見陷阱與最佳實踐,帶你一步步完成 Docker 化 FastAPI,讓你的 API 能在任何地方穩定運行。


核心概念

1. 為什麼要 Docker 化 FastAPI?

  • 環境一致性:開發、測試、正式環境皆使用相同的映像檔,避免版本衝突。
  • 可移植性:只要有 Docker Engine,就能在本機、VM、雲端或 Kubernetes 上執行。
  • 彈性伸縮:配合 Docker Compose 或 Kubernetes,輕鬆水平擴展多個實例。
  • 資源隔離:容器的 CPU、記憶體上限可自行設定,避免單一服務吃光主機資源。

2. Docker 基本構成

元件 說明
Dockerfile 定義如何建構映像檔的腳本,包含基底映像、安裝套件、複製程式碼等步驟。
Image 由 Dockerfile 產生的只讀檔案系統快照,可視為「程式碼 + 環境」的完整包装。
Container 從 Image 啟動的執行實例,具備獨立的網路、檔案系統與資源限制。
Docker Compose 用 YAML 描述多容器服務的部署方式,適合開發與小型測試環境。

3. FastAPI 常見的 Docker 化方式

  1. 直接使用官方 Python 基底映像:簡單且適合小型專案。
  2. 使用 Uvicorn + Gunicorn 組合:在生產環境中提供多工作者 (worker) 支援,提高併發效能。
  3. 多階段建構 (Multi‑stage Build):先在建置階段安裝依賴、編譯程式,最後只留下執行階段所需的最小檔案,減少映像檔大小。

程式碼範例

範例 1:最簡單的 FastAPI 應用 (app/main.py)

# app/main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    """回傳簡單訊息,測試用"""
    return {"message": "Hello, Dockerized FastAPI!"}

註解:這是一個最小化的 FastAPI 程式,只需要 fastapiuvicorn 兩個套件即可運行。

範例 2:Dockerfile(單階段)

# Dockerfile
FROM python:3.12-slim

# 設定工作目錄
WORKDIR /app

# 複製需求檔並安裝相依套件
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 複製程式碼
COPY . .

# 暴露 FastAPI 預設埠號 8000
EXPOSE 8000

# 使用 Uvicorn 啟動應用
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

說明

  • python:3.12-slim 為輕量化的官方映像。
  • --no-cache-dir 減少映像檔大小。
  • EXPOSE 僅作為文件說明,實際埠號映射在 docker run 時指定。

範例 3:多階段建構(減少映像檔大小)

# Dockerfile (multi-stage)
# ---------- Build Stage ----------
FROM python:3.12-slim AS builder

WORKDIR /app

# 安裝 build-essential,若有 C 擴充套件需求
RUN apt-get update && apt-get install -y --no-install-recommends gcc && \
    rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

# ---------- Runtime Stage ----------
FROM python:3.12-slim

WORKDIR /app

# 只複製已安裝好的套件
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH

# 複製程式碼
COPY . .

EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

重點

  • 兩個階段builder 用於安裝依賴,runtime 只保留最終執行所需的檔案,映像檔大小可減至原本的 30%~50%。
  • ENV PATH 確保使用者安裝的套件能被正確呼叫。

範例 4:使用 Gunicorn + Uvicorn workers(生產環境)

# Dockerfile (Gunicorn)
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

# 使用 Gunicorn 啟動,worker 為 Uvicorn workers
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "-w", "4", "-b", "0.0.0.0:8000", "app.main:app"]

說明

  • -w 4 代表啟動 4 個 worker,根據 CPU 核心數調整。
  • Gunicorn 能自動管理 worker 重啟、超時等,適合長時間服務。

範例 5:Docker Compose 組合 FastAPI 與 PostgreSQL

# docker-compose.yml
version: "3.9"

services:
  api:
    build: .
    container_name: fastapi_app
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://postgres:example@db:5432/mydb
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    container_name: postgres_db
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: example
      POSTGRES_DB: mydb
    volumes:
      - pg_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  pg_data:

重點

  • depends_on 確保資料庫先啟動。
  • 使用 環境變數 把資料庫連線字串注入 FastAPI,保持程式碼與設定分離。
  • volumes 提供資料持久化,避免容器重啟時資料遺失。

常見陷阱與最佳實踐

陷阱 說明 解決方案
映像檔過大 把開發環境、測試套件一起打包。 使用 多階段建構,只保留執行時必要的檔案。
未設定 HOST=0.0.0.0 Uvicorn 只在 localhost 監聽,外部無法存取。 CMD 或環境變數中明確指定 --host 0.0.0.0
依賴套件版本不固定 requirements.txt 中未鎖定版本,導致映像不一致。 使用 pip freeze > requirements.txt,或採用 Poetry / Pipenv 管理。
資料庫連線資訊寫死程式碼 部署到不同環境需要改程式。 把連線字串放在 環境變數,並使用 pydantic.BaseSettings 讀取。
容器資源未限制 容器可能佔用全部 CPU、記憶體。 docker rundocker-compose 中使用 cpusmem_limit 等參數。
未使用健康檢查 Orchestrator 無法偵測服務失敗。 在 Dockerfile 或 Compose 中加入 HEALTHCHECK 指令。

健康檢查範例

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8000/health || exit 1

說明:FastAPI 必須提供 /health endpoint 回傳 200,Orchestrator 會依此判斷容器是否健康。

建議的目錄結構

project/
├─ app/
│   ├─ __init__.py
│   ├─ main.py
│   └─ routers/
│       └─ items.py
├─ tests/
│   └─ test_main.py
├─ Dockerfile
├─ docker-compose.yml
├─ requirements.txt
└─ README.md

保持 apptests 分離,Dockerfile 只需要 COPY app/ .,測試則在 CI pipeline 中執行。


實際應用場景

  1. 微服務架構
    每個功能模組(如使用者、商品、訂單)都以獨立的 FastAPI 容器部署,透過 API GatewayService Mesh 進行統一路由與安全管控。

  2. CI/CD 自動化

    • 在 GitHub Actions 中使用 docker build -t myapp:${{ github.sha }} 建置映像。
    • 推送至 Docker Registry(Docker Hub、GitHub Packages、Harbor)。
    • 部署至 Kubernetes 叢集或 AWS ECS,完成 藍綠部署滾動更新
  3. 本機開發環境
    使用 docker-compose up -d 同時啟動 API、資料庫與 Redis,開發者只需要關注程式碼,而不必安裝任何資料庫或套件。

  4. 邊緣運算或 IoT
    在資源受限的設備(如樹莓派)上跑輕量化的 FastAPI 容器,提供本地化的資料收集與即時分析 API。


總結

Docker 化 FastAPI 不僅能解決 環境不一致部署繁瑣 的問題,更為 水平擴展持續交付多服務協作 打下堅實基礎。本文從概念說明、實作範例(單階段、Multi‑stage、Gunicorn、Docker Compose)到常見陷阱與最佳實踐,提供了一套完整的工作流程:

  1. 編寫乾淨的 FastAPI 程式碼,使用環境變數管理設定。
  2. 設計精簡的 Dockerfile,盡可能採用多階段建構以縮小映像。
  3. 使用 Docker ComposeKubernetes 進行多容器協調,加入健康檢查與資源限制。
  4. 在 CI/CD 中自動建置、測試、推送,確保每一次部署都是可追溯且可靠的。

掌握以上技巧後,你就能在開發階段就享受到「一次建置、隨處執行」的便利,讓 FastAPI 成為企業級服務的可靠基石。快把這些步驟套用到自己的專案,體驗容器化帶來的效率與穩定性吧! 🚀