經過了 28 天的學習與實戰,我們終於來到了最後的關鍵一哩路:部署。一個應用程式無論功能多強大,如果不能穩定地在伺服器上運行,就無法真正發揮價值。今天,我們將探討如何將 FastAPI AI 應用打包、管理,並透過反向代理提供服務,甚至啟用 GPU 支援。
今天我們將採用一套更現代化、整合度更高的工具來完成部署:Docker Compose 和 Caddy Server。這套組合能讓我們用一個指令就啟動包含應用、資料庫和反向代理在內的完整服務。
如果說 Dockerfile 是用來定義「一個」容器的藍圖,那麼 Docker Compose 就是用來定義和運行「多個」容器應用的劇本。我們可以透過一個 docker-compose.yml
設定檔,來描述我們的服務架構,例如:「我的應用需要一個 FastAPI 容器、一個 PostgreSQL 資料庫容器,以及一個 Caddy 反向代理容器」,然後用 docker-compose up
指令一鍵啟動所有服務。
之前我們提到了 Nginx,而 Caddy 則是一個更年輕的替代方案,它最大的特色就是自動化 HTTPS。只要您的伺服器有公網 IP 和一個指向它的域名,Caddy 就會自動向 Let's Encrypt 申請、設定並續訂 SSL 憑證,完全無需手動操作,極大地簡化了安全設定。
一個基礎的 Caddyfile
設定極其簡潔:
Caddyfile
your-domain.com {
# 將所有請求反向代理到名為 "fastapi_app" 的容器的 8000 port
reverse_proxy fastapi_app:8000
}
這邊就簡單地把 80 port 導進來就好:
:80 {
reverse_proxy fastapi_app:8000
}
現在,讓我們用 docker-compose.yml
把所有東西串起來。請確保您的專案目錄結構如下:
.
├── app/
│ ├── main.py # FastAPI 程式碼
│ ├── requirements.txt # Python 依賴套件
│ └── Dockerfile.fastapi # FastAPI 的 Dockerfile
│
├── Caddyfile # Caddy 的設定檔
├── docker-compose.yaml # Docker Compose 主設定檔
└── .env # 環境變數 (用於存放密碼)
Dockerfile
這個檔案負責打包你的 FastAPI 應用。
# 步驟 1: 選擇包含 CUDA 和 Python 的基礎映像
# 我們選擇 CUDA 12.4.1 的開發版,它通常已包含 Python
FROM nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04
# 步驟 2: 設定環境變數,避免互動式提示
ENV TZ=Asia/Taipei
ENV DEBIAN_FRONTEND=noninteractive
# 步驟 3: 安裝 Python 3.10+ 和 pip
RUN apt-get update && apt-get install -y \
python3.10 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# 步驟 4: 設定工作目錄
WORKDIR /app
# 步驟 5: 複製 requirements.txt 並安裝依賴套件
COPY ./requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
# 步驟 6: 複製應用程式程式碼
COPY . .
# 步驟 7: 開放容器的 8000 port
EXPOSE 8000
# 步驟 8: 執行 FastAPI 服務
CMD ["fastapi", "run", "main.py", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
這個檔案定義了我們的三個服務以及它們之間的關係。
version: "3.9"
services:
# 1. FastAPI 應用程式服務 (支援 GPU)
fastapi_app:
build:
context: ./app
dockerfile: Dockerfile.fastapi
restart: unless-stopped
networks:
- app_network
depends_on:
- db
# <<<<<<<< 這是啟用 GPU 的關鍵設定 >>>>>>>>
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all # "all" 表示使用所有可用的 GPU
capabilities: [gpu]
# 2. PostgreSQL 資料庫服務
db:
image: postgres:15-alpine
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- app_network
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
# 3. Caddy 反向代理服務
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
networks:
- app_network
depends_on:
- fastapi_app
# 定義網路和資料卷
networks:
app_network:
driver: bridge
volumes:
postgres_data:
其中 fastapi_app
服務中有一個 deploy
區塊:
deploy
: 這是 Docker Compose 中用來定義服務部署與執行階段相關設定的標準區塊。resources.reservations.devices
: 我們在這裡宣告這個服務需要預留硬體資源,具體來說是「裝置 (devices)」。driver: nvidia
: 指定我們要使用的是 NVIDIA 的驅動。count: all
: 表示請求主機上「所有」可用的 GPU。您也可以指定特定的 GPU 數量(例如 count: 1)或特定的 GPU ID。capabilities: [gpu]
: 這是必須的選項,用來賦予容器存取 GPU 的能力。重要提醒:要讓 Docker 容器能夠使用 GPU,系統必須額外安裝 NVIDIA Container Toolkit。
如果沒有安裝,就直接啟動的話,會看到這個錯誤:
Error response from daemon: could not select device driver "nvidia" with capabilities: [[gpu]]
詳細的安裝說明可以參考文件。以下將以 Ubuntu 系統為例進行說明:
在 Ubuntu/Debian 系統上安裝 NVIDIA Container Toolkit:
# 新增 NVIDIA 的套件庫
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# 更新
sudo apt-get update
# 安裝 NVIDIA Container Toolkit
export NVIDIA_CONTAINER_TOOLKIT_VERSION=1.17.8-1
sudo apt-get install -y \
nvidia-container-toolkit=${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
nvidia-container-toolkit-base=${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
libnvidia-container-tools=${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
libnvidia-container1=${NVIDIA_CONTAINER_TOOLKIT_VERSION}
# 重新啟動 Docker 服務
sudo systemctl restart docker
安裝完成後,可以用以下指令測試 GPU 是否可在容器中正常使用:
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
或是也可以直接在 FastAPI 的 main.py
加入一些測試的程式碼:
import torch
from fastapi import FastAPI
from pydantic import BaseModel, Field
from typing import List, Optional
# --- Pydantic Models for Response ---
class GpuDevice(BaseModel):
index: int = Field(..., description="GPU 裝置索引")
name: str = Field(..., description="GPU 型號名稱")
class GpuInfo(BaseModel):
cuda_available: bool = Field(..., description="CUDA 是否可用")
device_count: int = Field(..., description="可用的 GPU 數量")
devices: Optional[List[GpuDevice]] = Field(None, description="GPU 裝置列表")
# --- FastAPI App ---
app = FastAPI(
title="GPU Check API",
description="一個用於檢查 PyTorch CUDA 可用性的簡單 API",
version="1.0.0"
)
@app.get("/api/gpu-check", response_model=GpuInfo)
def check_gpu_status():
"""
檢查 PyTorch 是否可以使用 CUDA GPU,並返回詳細資訊。
"""
is_available = torch.cuda.is_available()
device_count = torch.cuda.device_count() if is_available else 0
devices_info = []
if is_available:
for i in range(device_count):
devices_info.append(
GpuDevice(index=i, name=torch.cuda.get_device_name(i))
)
return GpuInfo(
cuda_available=is_available,
device_count=device_count,
devices=devices_info if devices_info else None
)
@app.get("/")
def read_root():
return {"message": "Welcome to the GPU Check API. Go to /api/gpu-check to see GPU status."}
準備好以上三個檔案 (Dockerfile
, Caddyfile
, docker-compose.yml
) 後,只需在專案根目錄執行一個指令:
# -d 參數代表在背景分離模式 (detached mode) 運行
docker compose up --build -d
Caddy 會自動偵測到 Caddyfile
的設定,開始代理流量到你的 FastAPI 應用,如果設定了域名,它還會默默地在背景幫你處理好 HTTPS 的一切。至此,一個包含資料庫、應用和安全反向代理的生產級服務就成功運行起來了!
可以使用 Postman 測試一下 API (http://localhost/api/gpu-check
)
也可以進入 Docker 容器中測試 nvidia-smi
指令,有 Docker Desktop 的話就可以直接從 UI 介面上進去下指令:
或是直接在 terminal 下指令也可以
今天學習了使用 Docker Compose 和 Caddy 來部署 FastAPI 應用。透過一個指令即可啟動包含 GPU 支援的完整服務架構。