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 化方式
- 直接使用官方 Python 基底映像:簡單且適合小型專案。
- 使用 Uvicorn + Gunicorn 組合:在生產環境中提供多工作者 (worker) 支援,提高併發效能。
- 多階段建構 (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 程式,只需要
fastapi與uvicorn兩個套件即可運行。
範例 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 run 或 docker-compose 中使用 cpus、mem_limit 等參數。 |
| 未使用健康檢查 | Orchestrator 無法偵測服務失敗。 | 在 Dockerfile 或 Compose 中加入 HEALTHCHECK 指令。 |
健康檢查範例
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8000/health || exit 1
說明:FastAPI 必須提供
/healthendpoint 回傳 200,Orchestrator 會依此判斷容器是否健康。
建議的目錄結構
project/
├─ app/
│ ├─ __init__.py
│ ├─ main.py
│ └─ routers/
│ └─ items.py
├─ tests/
│ └─ test_main.py
├─ Dockerfile
├─ docker-compose.yml
├─ requirements.txt
└─ README.md
保持 app 與 tests 分離,Dockerfile 只需要 COPY app/ .,測試則在 CI pipeline 中執行。
實際應用場景
微服務架構
每個功能模組(如使用者、商品、訂單)都以獨立的 FastAPI 容器部署,透過 API Gateway 或 Service Mesh 進行統一路由與安全管控。CI/CD 自動化
- 在 GitHub Actions 中使用
docker build -t myapp:${{ github.sha }}建置映像。 - 推送至 Docker Registry(Docker Hub、GitHub Packages、Harbor)。
- 部署至 Kubernetes 叢集或 AWS ECS,完成 藍綠部署 或 滾動更新。
- 在 GitHub Actions 中使用
本機開發環境
使用docker-compose up -d同時啟動 API、資料庫與 Redis,開發者只需要關注程式碼,而不必安裝任何資料庫或套件。邊緣運算或 IoT
在資源受限的設備(如樹莓派)上跑輕量化的 FastAPI 容器,提供本地化的資料收集與即時分析 API。
總結
Docker 化 FastAPI 不僅能解決 環境不一致、部署繁瑣 的問題,更為 水平擴展、持續交付、多服務協作 打下堅實基礎。本文從概念說明、實作範例(單階段、Multi‑stage、Gunicorn、Docker Compose)到常見陷阱與最佳實踐,提供了一套完整的工作流程:
- 編寫乾淨的 FastAPI 程式碼,使用環境變數管理設定。
- 設計精簡的 Dockerfile,盡可能採用多階段建構以縮小映像。
- 使用 Docker Compose 或 Kubernetes 進行多容器協調,加入健康檢查與資源限制。
- 在 CI/CD 中自動建置、測試、推送,確保每一次部署都是可追溯且可靠的。
掌握以上技巧後,你就能在開發階段就享受到「一次建置、隨處執行」的便利,讓 FastAPI 成為企業級服務的可靠基石。快把這些步驟套用到自己的專案,體驗容器化帶來的效率與穩定性吧! 🚀