Skip to content

12.1 生产配置:DEBUG=False, SECRET_KEY 安全管理

在开发阶段,FastAPI 默认开启调试模式(debug=True),这会暴露详细的错误信息,方便开发者排查问题。但在生产环境中,必须关闭调试模式,防止敏感信息泄露。

同时,SECRET_KEY 是用于 JWT 签名、会话加密等安全功能的核心密钥,绝不能硬编码在代码中,更不能提交到版本控制系统(如 Git)。

核心做法

  • 使用 .env 文件存储敏感配置
  • 通过 Pydantic BaseSettings 自动加载环境变量
  • 在生产部署时通过环境变量覆盖 .env 中的值

下面是一个安全的配置管理示例:

python
# app/core/config.py
from pydantic_settings import BaseSettings  # 注意:Pydantic v2 中是 pydantic_settings

class Settings(BaseSettings):
    # 应用基础配置
    APP_NAME: str = "My FastAPI App"
    DEBUG: bool = False  # 生产环境必须为 False
    
    # 安全密钥(从环境变量读取,若无则报错)
    SECRET_KEY: str
    
    # 数据库连接
    DATABASE_URL: str
    
    # Redis 配置
    REDIS_HOST: str = "localhost"
    REDIS_PORT: int = 6379
    
    class Config:
        env_file = ".env"  # 指定 .env 文件路径
        env_file_encoding = "utf-8"

# 创建全局配置实例
settings = Settings()

对应的 .env 文件(不要提交到 Git):

env
DEBUG=False
SECRET_KEY=your_very_long_random_secret_key_here_123!@#
DATABASE_URL=mysql+asyncmy://user:password@localhost/dbname
REDIS_HOST=redis

小提示:生成强 SECRET_KEY 可以用 Python 命令: python -c "import secrets; print(secrets.token_urlsafe(32))"

这一节讲了如何在生产环境中安全地管理配置,特别是关闭调试模式和保护 SECRET_KEY,这是保障应用安全的第一道防线。

12.2 Docker 化:多阶段构建镜像(包含 MySQL + Redis)

为了确保开发、测试、生产环境一致,我们使用 Docker 容器化部署。采用 多阶段构建 可以减小最终镜像体积,提升安全性。

项目根目录创建 Dockerfile

dockerfile
# 第一阶段:构建依赖
FROM python:3.10-slim AS builder

# 设置工作目录
WORKDIR /app

# 安装系统依赖(可选)
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    && rm -rf /var/lib/apt/lists/*

# 复制依赖文件
COPY requirements.txt .

# 安装 Python 依赖到虚拟环境(减小体积)
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --no-cache-dir --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt


# 第二阶段:运行时镜像
FROM python:3.10-slim

# 创建非 root 用户(安全最佳实践)
RUN useradd --create-home --shell /bin/bash app
USER app
WORKDIR /home/app

# 从 builder 阶段复制虚拟环境
COPY --from=builder --chown=app:app /opt/venv /opt/venv

# 复制应用代码
COPY --chown=app:app . .

# 激活虚拟环境
ENV PATH="/opt/venv/bin:$PATH"

# 暴露端口
EXPOSE 8000

# 启动命令
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

同时,使用 docker-compose.yml 编排整个服务(含 MySQL 和 Redis):

yaml
# docker-compose.yml
version: '3.8'

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: myapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - "3306:3306"

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  web:
    build: .
    depends_on:
      - db
      - redis
    environment:
      - DATABASE_URL=mysql+asyncmy://appuser:apppass@db/myapp
      - REDIS_HOST=redis
      - SECRET_KEY=production_secret_key_change_me
      - DEBUG=False
    ports:
      - "8000:8000"
    volumes:
      - ./app:/home/app/app  # 开发时可挂载,生产建议移除

volumes:
  mysql_data:

这一节展示了如何通过 Docker 多阶段构建优化镜像,并用 docker-compose 统一管理 FastAPI、MySQL 和 Redis 三个服务,实现“一次构建,随处运行”。

12.3 进程管理:Uvicorn + Gunicorn(多 worker)

虽然 Uvicorn 本身支持异步高并发,但在生产环境中,通常将其作为 ASGI 工作进程,由 Gunicorn 作为进程管理器来启动多个 Uvicorn worker,以充分利用多核 CPU。

首先安装 Gunicorn 和 Uvicorn 的 Gunicorn worker:

bash
pip install gunicorn uvicorn[standard]

然后创建 Gunicorn 配置文件 gunicorn_conf.py

python
# gunicorn_conf.py
import multiprocessing

# 绑定地址
bind = "0.0.0.0:8000"

# 工作进程数:通常为 CPU 核心数 + 1
workers = multiprocessing.cpu_count() + 1

# 每个 worker 使用 Uvicorn 的 ASGI 工作类
worker_class = "uvicorn.workers.UvicornWorker"

# 最大请求处理数后重启 worker(防内存泄漏)
max_requests = 1000
max_requests_jitter = 100

# 超时设置(秒)
timeout = 60

# 日志级别
loglevel = "info"

修改 Dockerfile 的启动命令:

dockerfile
# 替换原来的 CMD
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "app.main:app", "-c", "gunicorn_conf.py"]

或者在 docker-compose.yml 中指定:

yaml
# 在 web 服务下
command: gunicorn -k uvicorn.workers.UvicornWorker app.main:app -c gunicorn_conf.py

注意:由于 FastAPI 是纯异步应用,每个 Uvicorn worker 本身就能处理大量并发连接。增加 worker 数量主要是为了利用多核并行处理 CPU 密集型任务或提高容错性。

这一节介绍了如何用 Gunicorn 管理多个 Uvicorn worker,提升应用的吞吐量和稳定性,是生产部署的标准做法。

12.4 Nginx 反向代理:静态文件 + HTTPS 配置

Nginx 作为反向代理,可以:

  • 处理 HTTPS(SSL/TLS 终止)
  • 提供静态文件服务(如前端资源)
  • 负载均衡(多实例)
  • 缓存、限流等高级功能

首先,在项目中创建 nginx.conf

nginx
# nginx.conf
upstream fastapi_app {
    server web:8000;  # docker-compose 中的服务名
}

server {
    listen 80;
    server_name your-domain.com;

    # 强制跳转 HTTPS(生产环境推荐)
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;

    # SSL 证书(需提前申请,如 Let's Encrypt)
    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # 安全头
    add_header Strict-Transport-Security "max-age=31536000" always;

    # API 路由代理到 FastAPI
    location / {
        proxy_pass http://fastapi_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 静态文件(如 Swagger UI、前端打包文件)
    location /static/ {
        alias /var/www/static/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

更新 docker-compose.yml 加入 Nginx 服务:

yaml
services:
  # ... 其他服务

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./ssl:/etc/nginx/ssl  # 存放证书
      - ./static:/var/www/static  # 静态文件目录
    depends_on:
      - web

HTTPS 小贴士:可使用 Certbot 自动申请 Let's Encrypt 免费证书,或在云服务商(如阿里云、腾讯云)控制台一键部署。

这一节讲解了如何用 Nginx 作为反向代理,处理 HTTPS 和静态文件,让 FastAPI 专注于业务逻辑,提升整体架构的安全性和性能。