Files
Profeto/docs/06-deployment.md
T
WorkBuddy 6bdb1f8ae6 docs(deploy): 补充生产上线检查清单(README + docs/06)
- docs/06 新增「生产上线检查清单」10 项:APP_ENV / SECRET_KEY 强随机 /
  管理鉴权二选一 / 数据库强密码 / HTTPS+Cookie Secure /
  TRUST_PROXY_HEADERS+X-Forwarded-For / Nginx limit_req 限流前置
  (应用内限流与 KeyRing 单进程限制) / uvicorn 单 worker /
  /health 与 /health/ready / alembic 迁移已内置
- README 在部署说明后加同名精简清单,链接到 docs/06 详情
- 全部条目均对齐真实实现(security_check 弱值黑名单、auth.py
  secure=production、deps.py TRUST_PROXY 解析、app.py 双健康检查、
  compose/Dockerfile 内置迁移);纯文档,未改业务逻辑
2026-09-21 21:02:16 +08:00

9.4 KiB
Raw Blame History

06 · 部署

前置要求

  • Docker & Docker Compose
  • bzzoiro API Key(必填)
  • LLM API Key(必填,OpenAI / Deepseek / 兼容接口)

Docker Compose 部署(推荐)

# 1. 配置环境变量
cp .env.example .env
# 编辑 .env: 填 LLM_API_KEY / BZZOIRO_KEY

# 2. 启动(自动执行数据库迁移)
docker compose up -d --build

# 3. 验证
curl http://localhost:8000/health

docker-compose.yml 包含 3 个服务:

服务 端口 说明
postgres 5433 PostgreSQL 16
api 8000 FastAPI 应用(启动时自动执行 alembic upgrade head)
frontend 3000 React 前端(多阶段构建,nginx 服务静态文件)

数据卷 pgdata 持久化数据库,重启不丢数据。

注意: api 服务启动时会先执行 alembic upgrade head 迁移数据库,再启动 uvicorn。 容器内数据库连接自动使用 postgres 服务名(通过 compose environment 覆盖 .env 中的 DB_HOST)。

生产上线检查清单

公网上线前逐项勾选。第 14 项由 src/core/security_check.pyAPP_ENV=production 启动时强制校验,不满足直接拒绝启动(开发环境仅告警);管理鉴权另有请求期 fail-closed(503)。

  • 1. APP_ENV=production — 安全校验、Cookie Secure、管理端点 fail-closed 均以它为总开关
  • 2. SECRET_KEY 强随机 — 用 openssl rand -base64 32 生成;禁止弱值/短值(弱值黑名单会拒绝启动,含把生成指令原样粘进去的情况)
  • 3. 管理鉴权至少其一ADMIN_PASSWORDADMIN_API_KEY(后台改过密码后以数据库哈希优先);两者皆空时管理接口 503
  • 4. 数据库强密码 — 禁止 football:football 等示例弱密码(启动校验会拒绝);compose 的 POSTGRES_PASSWORD 必填,缺失时容器拒绝启动
  • 5. HTTPS — 由反代(Nginx/Caddy)终结 TLS;APP_ENV=production 下会话 Cookie 自动 Secure(且 HttpOnly + SameSite=Lax)
  • 6. 反代信任头TRUST_PROXY_HEADERS=True,且仅可信反代可达 API;反代需设置 X-Forwarded-For($proxy_add_x_forwarded_for)与 X-Real-IP,否则限流/日志按反代 IP 计数
  • 7. 限流前置到网关 — 推荐 Nginx limit_req(配置见安全与限流);应用内限流与 KeyRing 为单进程内存实现,多 worker 各自独立计数会把实际配额放大 N 倍(启动时会打印一次性告警)
  • 8. uvicorn 单 worker — compose/Dockerfile 默认单 worker,保持即可;需横向扩容时先在网关统一限流,再起多实例(每实例仍单 worker)
  • 9. 启动后健康检查curl /health 返回 200(存活);curl /health/ready 返回 200(就绪,校验数据库连通,不可达时 503)
  • 10. 数据库迁移 — compose/Dockerfile 启动命令已内置 alembic upgrade head && uvicorn …,升级镜像重启即自动迁移,无需手动执行

本地开发部署

# 1. 安装依赖
pip install -e ".[dev]"

# 2. 启动 PostgreSQL(单独)
docker run -d --name profeto-pg \
  -e POSTGRES_USER=football -e POSTGRES_PASSWORD=football -e POSTGRES_DB=football \
  -p 5432:5432 postgres:16-alpine

# 3. 配置 .env
cp .env.example .env

# 4. 建表
alembic upgrade head

# 5. 启动 API
uvicorn src.api.app:app --reload

# 6. 启动前端(另一个终端)
cd frontend && npm install && npm run dev

访问:

环境变量

变量 必需 默认值 说明
APP_ENV development production / development
LOG_LEVEL INFO 日志级别
API_PORT 8000 API 服务端口映射
FRONTEND_PORT 3000 前端服务端口映射
POSTGRES_USER PostgreSQL 用户名
POSTGRES_PASSWORD PostgreSQL 密码
POSTGRES_DB football PostgreSQL 数据库名
POSTGRES_PORT 5433 PostgreSQL 端口映射
DATABASE_URL PostgreSQL 连接 URL(Docker 内会被覆盖)
LLM_PROVIDER openai 提供商名(仅标记)
LLM_API_KEY API Key
LLM_BASE_URL https://api.openai.com/v1 接口地址(Ollama/Deepseek 用)
LLM_MODEL gpt-4o 默认模型
LLM_TIMEOUT 60 单次调用超时(秒)
LLM_SPECIALIST_MODEL 专家模型(回落 LLM_MODEL)
LLM_AGGREGATOR_MODEL 终裁模型(回落 LLM_MODEL)
BZZOIRO_KEY bzzoiro 数据源 Key(唯一数据源)
CORS_ORIGINS http://localhost:5173,... 允许的跨域来源
SECRET_KEY 加密主密钥(生产环境必填)
ADMIN_PASSWORD 管理后台密码(留空=不启用)
ADMIN_API_KEY 机器/脚本调用的 API Key

LLM 提供商配置示例

OpenAI

LLM_API_KEY=sk-xxxx
LLM_BASE_URL=https://api.openai.com/v1
LLM_MODEL=gpt-4o

Deepseek

LLM_API_KEY=sk-xxxx
LLM_BASE_URL=https://api.deepseek.com/v1
LLM_MODEL=deepseek-chat

Ollama(本地)

LLM_API_KEY=ollama
LLM_BASE_URL=http://localhost:11434/v1
LLM_MODEL=llama3.1

分档配置(专家用便宜模型)

LLM_MODEL=gpt-4o
LLM_SPECIALIST_MODEL=gpt-4o-mini
LLM_AGGREGATOR_MODEL=gpt-4o

数据库迁移

Alembic 管理 schema 变更:

# 查看当前版本
alembic current

# 升级到最新
alembic upgrade head

# 回退一级
alembic downgrade -1

# 生成新迁移(改 models.py 后)
alembic revision --autogenerate -m "描述"

# 空迁移(手动写 SQL)
alembic revision -m "描述"

Docker Compose 自动迁移: api 容器启动时会自动执行 alembic upgrade head, 无需手动运行。本地开发时需手动执行迁移。

已有迁移:

  • 0001_initial: 初始 5 张表
  • 0002_agent_outputs: predictions 加 mode + agent_outputs
  • 0003_injuries: 增加 injuries 表
  • 0004_snapshot_and_constraints: 增加约束
  • 0005_prediction_status_and_stats_provenance: 增加时间语义
  • 0006-0012: 后续 schema 调整、约束命名对齐、partial unique index 等

备份与恢复

# 备份
docker exec profeto-postgres pg_dump -U football football > backup.sql

# 恢复
cat backup.sql | docker exec -i profeto-postgres psql -U football football

监控

健康检查

端点 含义 HTTP 状态码
/health 存活检查(liveness) 始终 200(进程在跑即活)
/health/ready 就绪检查(readiness) DB 可达 200,不可达 503

探针配置

Docker Compose

docker-compose.yml 已为 api 服务配置 readiness:

healthcheck:
  test: ["CMD-SHELL", "curl -sf http://localhost:8000/health/ready || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 10s

要点:必须指向 /health/ready 而非 /health——后者始终 200,在数据库故障时仍会接收流量,导致请求全部失败。

Kubernetes

livenessProbe:
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 15
readinessProbe:
  httpGet:
    path: /health/ready
    port: 8000
  initialDelaySeconds: 10
  periodSeconds: 10
  failureThreshold: 3

两探针必须区分:

  • livenessProbe/health:仅在进程死锁/崩溃时重启,避免误杀。
  • readinessProbe/health/ready:DB 不可用时停止转发流量,恢复后自动切回。

验证

# 宿主机直接运行(经本地 8000 端口)
python3 tests/test_health_ready.py

评估

安全与限流

内存限流(按进程)

/api/v1/predict 与登录防爆破均使用进程内内存计数:

机制 位置 局限
/predict 限流 _RateLimiter(内存) 每 worker 独立计数,不共享
登录防爆破 _fail_times(内存) 同上

多 worker 部署时(如 uvicorn --workers 4),每进程各自计数,实际限额为 N × 单进程限制

公网部署建议

┌─────────┐     ┌──────────┐     ┌──────────┐
│  Client │────▶│  Nginx   │────▶│  API     │
│         │     │ 限流层    │     │ 内存限流  │
└─────────┘     └──────────┘     └──────────┘

推荐配置:

  1. Nginx 层限流(第一道防线):

    limit_req_zone $binary_remote_addr zone=predict:10m rate=10r/m;
    location /api/v1/predict {
        limit_req zone=predict burst=20 nodelay;
        proxy_pass http://api:8000;
    }
    
  2. TRUST_PROXY_HEADERS=True 时必须由可信反代设置 X-Forwarded-For:

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
    • 若为 False: 仅用 request.client.host,忽略 X-Forwarded-For,防伪造
    • 若为 True: 解析 X-Forwarded-For 第一个 IP,反代后方可信
  3. 生产环境必须配置管理鉴权:

    APP_ENV=production
    REQUIRE_ADMIN_AUTH=True
    ADMIN_PASSWORD=your_secure_password
    

    未配置时 /admin 等管理接口返回 503。

参数调优

参数 默认 说明
_predict_limiter.max_requests 10 每分钟每 IP 最大请求数
_predict_limiter.window_seconds 60 滑动窗口时长
ADMIN_SESSION_TTL_HOURS 168 管理会话有效期(天)