本文 AI 產出,尚未審核

FastAPI 部署與架構:Serverless 部署(Vercel / Cloud Run)


簡介

在現代的 Web 應用開發中,快速迭代彈性伸縮已成為不可或缺的需求。FastAPI 以其高效能、易用的型別提示與自動產生 OpenAPI 文件的特性,迅速成為 Python 生態系統中最受歡迎的框架之一。當我們完成 API 開發後,如何把服務以 Serverless 方式部署,讓它只在需要時才啟動、只為實際使用的請求付費,成為下一個重要課題。

本篇文章聚焦於兩個主流的 Serverless 平台——VercelGoogle Cloud Run,說明如何將 FastAPI 應用無縫搬上雲端,並提供實作範例、常見陷阱與最佳實踐,協助你在開發與部署之間建立穩固的橋樑。


核心概念

1. 為什麼選擇 Serverless?

特性 傳統 VM / Container Serverless
成本 持續付費(CPU、記憶體) 按請求計費,閒置不收費
伸縮 手動或自動調整,需設定上限 自動依流量彈性擴張
部署速度 需要建置映像檔、設定環境 直接推送程式碼或容器,即可上線
維運負擔 需要管理 OS、更新、監控 平台負責底層基礎設施

對於 API 這類「請求驅動」的服務,Serverless 能顯著降低成本,同時提供即時的彈性伸縮,特別適合 MVP、原型開發流量波動大的應用

2. FastAPI 與 ASGI

FastAPI 基於 ASGI(Asynchronous Server Gateway Interface)規範,這意味著它可以直接在支援 ASGI 的平台上執行,而不需要額外的 WSGI 包裝層。Vercel 與 Cloud Run 都支援容器化或直接執行 ASGI 應用,使得 FastAPI 的部署變得相當直接。

3. Vercel 與 Cloud Run 的差異

項目 Vercel Cloud Run
部署模型 Git‑Driven(自動建置) + Serverless Functions Container‑Driven(Docker) + Serverless
語言支援 原生支援 Node.js、Python(透過 vercel-python 任意支援 Docker 的語言
冷啟動 約 200‑500ms(根據函式大小) 約 500‑1000ms(容器啟動)
最大請求時限 60 秒(免費方案) 60 分鐘(可自訂)
計費方式 執行次數 + 執行時間 執行時間 + 記憶體配置

Vercel 更適合 前端與 API 同步部署,且開發者只需要撰寫簡單的 vercel.json 即可;而 Cloud Run 則提供更大的彈性(自訂容器、長時間執行、較高的 CPU 配置),適合 需要較高效能或較大規模的服務


程式碼範例

以下示範三個常見的部署方式,分別針對 Vercel、Cloud Run(Docker)以及 同時支援兩者的通用 Dockerfile。每段程式碼都附有詳細註解,方便你直接套用。

1️⃣ 基本 FastAPI 應用 (app/main.py)

# app/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List

app = FastAPI(title="Serverless FastAPI Demo")

class Item(BaseModel):
    id: int
    name: str
    price: float

# 假資料庫
FAKE_DB = [
    {"id": 1, "name": "Apple", "price": 2.5},
    {"id": 2, "name": "Banana", "price": 1.2},
]

@app.get("/items", response_model=List[Item])
async def list_items():
    """取得所有商品"""
    return FAKE_DB

@app.get("/items/{item_id}", response_model=Item)
async def get_item(item_id: int):
    """根據 ID 取得單一商品"""
    for item in FAKE_DB:
        if item["id"] == item_id:
            return item
    raise HTTPException(status_code=404, detail="Item not found")

@app.post("/items", response_model=Item, status_code=201)
async def create_item(item: Item):
    """新增商品"""
    FAKE_DB.append(item.dict())
    return item

小技巧:在開發階段使用 uvicorn app.main:app --reload,在部署時只需要把 app 物件暴露即可。


2️⃣ Vercel Serverless Function (api/index.py)

Vercel 會自動把 api/ 目錄下的檔案視為 Serverless Function。我們只需要把 FastAPI 包裝成 WSGI/ASGI 兼容的函式。

# api/index.py
import os
from fastapi import FastAPI
from fastapi.routing import APIRouter
from starlette.requests import Request
from starlette.responses import Response
from mangum import Mangum  # 讓 FastAPI 能在 AWS Lambda / Vercel 上跑

# 直接匯入我們前面寫好的 FastAPI 應用
from app.main import app as fastapi_app

# 使用 Mangum 包裝
handler = Mangum(fastapi_app)

def handler(event, context):
    """
    Vercel 會呼叫此函式,event 為 Lambda 事件格式。
    Mangum 會把它轉換成 ASGI 呼叫,回傳符合 Vercel 規範的結果。
    """
    return handler(event, context)

重要:Vercel 官方目前仍以 vercel-python 為主,若想直接部署 FastAPI,使用 Mangrove (Mangum) 這樣的適配器最簡單。請在 requirements.txt 中加入 fastapi, uvicorn, mangum

vercel.json

{
  "functions": {
    "api/index.py": {
      "runtime": "python3.11",
      "maxDuration": 60
    }
  }
}

說明maxDuration 設定函式最長執行時間(秒),超過會被強制終止。


3️⃣ Cloud Run Dockerfile(適用於任意平台)

Cloud Run 以容器為單位執行,因此只要把 FastAPI 包裝成一個 Docker image,然後推到 Container Registry(或 Artifact Registry)即可。

# Dockerfile
FROM python:3.11-slim

# 建立非 root 使用者,提升安全性
RUN useradd -m appuser
WORKDIR /app

# 安裝系統相依套件(如需要的話)
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# 複製需求檔與安裝
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 複製程式碼
COPY . .

# 以非 root 身份執行
USER appuser

# 使用 Uvicorn 作為 ASGI 伺服器,綁定 0.0.0.0:8080(Cloud Run 預設埠號)
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

requirements.txt

fastapi==0.110.0
uvicorn[standard]==0.27.0
gunicorn==21.2.0   # optional, 若想使用 gunicorn + uvicorn worker

部署步驟(概略)

# 1. 建立 Container Registry
gcloud artifacts repositories create my-repo --repository-format=docker --location=asia-east1

# 2. 建置 Docker 映像
docker build -t asia-east1-docker.pkg.dev/<PROJECT_ID>/my-repo/fastapi-serverless:latest .

# 3. 推送至 Registry
docker push asia-east1-docker.pkg.dev/<PROJECT_ID>/my-repo/fastapi-serverless:latest

# 4. 部署到 Cloud Run
gcloud run deploy fastapi-service \
  --image=asia-east1-docker.pkg.dev/<PROJECT_ID>/my-repo/fastapi-serverless:latest \
  --platform=managed \
  --region=asia-east1 \
  --allow-unauthenticated \
  --cpu=1 \
  --memory=512Mi \
  --max-instances=10

提示--max-instances 可以限制最大容器數量,避免突發流量產生過高費用。


4️⃣ 同時支援 Vercel 與 Cloud Run 的通用 Dockerfile

如果你想一次寫好 Dockerfile,然後在 Vercel(使用 vercel buildCloud Run 兩個平台皆能使用,只要把入口點改成 uvicorn,並在 vercel.json 設定 buildCommandoutputDirectory

# Dockerfile (通用版)
FROM python:3.11-slim

WORKDIR /app

# 安裝依賴
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 複製程式碼
COPY . .

# 暴露埠口(Vercel 會自動映射 3000,Cloud Run 需要 8080)
EXPOSE 3000 8080

# 預設指令
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "3000"]

注意:在 Vercel 使用 Docker 時,需要在 vercel.json 裡指定 buildCommanddocker build -t app .,並把 outputDirectory 設為 /(根目錄即為容器入口點)。


常見陷阱與最佳實踐

陷阱 可能的症狀 解決方案/最佳實踐
冷啟動延遲 第一次請求回應時間 > 1 秒 - 使用較小的容器基礎映像(python-slim
- 預熱(在 Cloud Run 設 --min-instances=1
- 在 Vercel 使用 vercel dev 本機測試,確保函式尺寸小
依賴未打包 部署後 500 錯誤,找不到模組 - 確認 requirements.txt 完整
- 在 Dockerfile 中使用 --no-cache-dir 減少層級錯誤
環境變數未傳遞 讀不到資料庫連線字串 - Vercel:在 Dashboard → Settings → Environment Variables 設定
- Cloud Run:gcloud run services update <service> --set-env-vars KEY=VALUE
請求時限超過 長時間的背景任務被中斷 - 把耗時工作移到 Cloud TasksPub/SubBackground Worker
- 若必須在 API 完成,可在 Cloud Run 調整 --timeout(最長 60 分鐘)
日誌與監控不足 無法追蹤錯誤或效能瓶頸 - Vercel:使用內建「Logs」或串接 Logflare
- Cloud Run:透過 Stackdriver LoggingTracing,並加上 uvicorn[standard]--log-level info
跨域(CORS)問題 前端呼叫失敗,出現 No 'Access-Control-Allow-Origin' header - 在 FastAPI 加入 from fastapi.middleware.cors import CORSMiddleware,設定允許來源

建議的最佳實踐

  1. 最小化容器大小:只安裝執行所需的套件,使用 python:*-slimalpine(若相依套件支援)。
  2. 使用非 root 用戶:在 Dockerfile 中建置 appuser,提升安全性。
  3. 分離長時間任務:將繁重的計算或 I/O 交給 Cloud Tasks、Pub/Sub 或 Cloud Functions,保持 API 的 快速回應
  4. 設定健康檢查:Cloud Run 允許自訂 /health 端點,確保容器在失敗時自動重啟。
  5. 版本化部署:利用 Git 標籤或 Cloud Run 的 revision 功能,快速回滾至先前穩定版本。

實際應用場景

場景 為何選 Serverless FastAPI 部署建議
行銷活動的即時報名系統 流量在活動期間會瞬間激增,平日幾乎為零 使用 Cloud Run 最小實例 0(零成本),設定自動擴展上限 100+
前端 Next.js + API 想把前端(Next.js)與 API 同時放在 Vercel,保持同一個域名 在 Vercel api/ 目錄使用 Mangum 包裝 FastAPI,前端直接呼叫 /api/...
機器學習模型推論 每筆請求需要載入模型(約 500MB),但請求頻率不高 把模型放在 Cloud Storage,使用 Cloud Run 高記憶體配置(2Gi)並設定 --max-instances=5
內部工具(管理介面) 員工偶爾使用,安全性需求較高 在 Cloud Run 加上 IAM 授權,僅允許特定 Google 帳號存取
多租戶 SaaS API 每個客戶都有獨立的子域名,需快速擴容 使用 Vercel 的 Edge Functions 搭配 FastAPI,利用 Edge 的全球快取降低延遲

總結

  • Serverless 為 FastAPI 提供了低成本、彈性伸縮與簡化運維的優勢。
  • Vercel 適合與前端緊密結合的小型或中等流量服務,部署方式以 functions 為主,透過 Mangum 可輕鬆包裝 FastAPI。
  • Google Cloud Run 則以 Docker 為核心,支援更高的 CPU、記憶體配置與較長的請求時限,適合需要較大資源或自訂執行環境的情境。
  • 透過 最佳實踐(最小化映像、非 root 用戶、分離長時間任務、設定健康檢查)與 常見陷阱 的避免策略,你的 FastAPI 服務將能在兩大平台上穩定運行,並在流量高峰時自動擴展。

掌握上述概念與步驟,你就能把 FastAPI API 以 Serverless 方式快速上線,讓開發者專注於業務邏輯,而不是底層基礎設施的維護。祝你部署順利,服務穩定成長! 🚀