部署指南
五种部署模式覆盖从本地试用到内网离线的全部场景。
部署模式总览
graph TD
Start{选择部署模式}
Start -->|本地试用| M1[Mode 1: Quick Trial]
Start -->|生产部署| Prod{基础设施}
Start -->|内网离线| Intra{基础设施}
Prod -->|自建 PG + Redis| M2A[Mode 2A: 自建基础设施]
Prod -->|云数据库 RDS| M2B[Mode 2B: 云数据库]
Intra -->|自建 PG + Redis| M3A[Mode 3A: 内网自建]
Intra -->|内部 DB 服务| M3B[Mode 3B: 内网托管DB]
| Mode | 场景 | 服务 | 数据库 | Compose 文件 |
|---|---|---|---|---|
| 1: Quick Trial | 本地试用 | backend + frontend | SQLite + InMemory | docker-compose.yml |
| 2A: Prod 自建 | 生产 + 自建基础设施 | nginx + backend + frontend + PG + Redis | 容器化 | docker-compose.prod.yml --profile infra |
| 2B: Prod 云数据库 | 生产 + RDS/ElastiCache | nginx + backend + frontend | 外部托管 | docker-compose.prod.yml |
| 3A: 内网 自建 | 离线/内网部署 | 同 2A | 容器化 | deploy/docker-compose.intranet.yml --profile infra |
| 3B: 内网 托管DB | 离线 + 内部DB服务 | nginx + backend + frontend | 内部托管 | deploy/docker-compose.intranet.yml |
关键区别:
- Mode 2 vs 1: Nginx 反向代理(单端口 80)、PG + Redis 持久化、Alembic 自动迁移
- Mode 3 vs 2:
image:替代build:,通过docker save/load离线部署,无需访问外部镜像仓库 - 2A/3A vs 2B/3B:
--profile infra控制是否启动 PG/Redis 容器
Mode 1: Quick Trial
最简部署,SQLite + InMemory RuntimeStore,适合本地试用和开发。
# 1. 配置环境变量
cp .env.example .env
# 编辑 .env,填入 API Keys 和 JWT secret
# 2. 启动
docker compose up -d
# 3. 创建管理员
docker compose exec backend python scripts/create_admin.py admin --password <your-password>
# 4. 访问
# 前端: http://localhost:3000
# API 文档: http://localhost:8000/docs(需设置 ARTIFACTFLOW_DEBUG=true)
注意事项:
- 前端 3000 → 后端 8000 跨端口,CORS 默认开启
- 数据存储在 Docker named volume
artifactflow_data - 不支持多副本(InMemory RuntimeStore 是单进程的)
Mode 2A: Production(自建基础设施)
完整生产部署,PG + Redis 容器化,Nginx 反向代理。
前置准备
# 1. 从模板创建 .env
cp deploy/.env.prod.example .env
# 2. 编辑 .env,必须填写:
# - ARTIFACTFLOW_JWT_SECRET(生成: python -c "import secrets; print(secrets.token_urlsafe(32))")
# - POSTGRES_PASSWORD(强密码)
# - DASHSCOPE_API_KEY(默认模型必填)
启动
首次初始化
# Alembic 自动迁移(容器 entrypoint 自动完成,无需手动)
# 确认迁移成功:
docker compose -f docker-compose.prod.yml logs backend | grep -i "alembic"
# 创建管理员
docker compose -f docker-compose.prod.yml exec backend \
python scripts/create_admin.py admin --password <your-password>
验证
# 健康检查(通过 Nginx)
curl http://localhost/health/ready
# 预期: {"status":"ok","db":"ok","redis":"ok"}
# 前端
open http://localhost
扩缩容
# 水平扩展 backend(Nginx 自动负载均衡)
docker compose -f docker-compose.prod.yml --profile infra up -d --scale backend=2
# 注意:首次启动多副本时,Alembic 迁移通过 PG advisory lock 串行化
# 只有一个副本执行迁移,其他副本等待并验证后再启动
Mode 2B: Production(云数据库)
使用外部 RDS + ElastiCache/Redis,不启动数据库容器。
配置
cp deploy/.env.prod.example .env
# 编辑 .env,修改连接地址:
# ARTIFACTFLOW_DATABASE_URL=postgresql+asyncpg://user:pass@your-rds-endpoint:5432/artifactflow
# ARTIFACTFLOW_REDIS_URL=redis://your-redis-endpoint:6379
# 删除或注释掉 POSTGRES_* 相关变量
启动
Mode 3: 内网离线部署
适用于无法访问外部网络的环境。使用预构建镜像,通过 docker save/load 传输。
构建发布包(在有网络的构建机上)
./scripts/release.sh 1.0.0
# 产出:
# dist/artifactflow-1.0.0.tar.gz (~500MB, 含全部 5 个镜像)
# dist/artifactflow-1.0.0.tar.gz.sha256 (校验文件)
部署(在目标内网机器上)
# 1. 传输文件到目标机器
scp dist/artifactflow-1.0.0.tar.gz deploy/ target:/opt/artifactflow/
# 2. 加载镜像
docker load < artifactflow-1.0.0.tar.gz
# 3. 配置
cp deploy/.env.intranet.example deploy/.env
# 编辑 deploy/.env,填写密码和 API Keys
# 内网 LLM:编辑 config/models/models.yaml,设置 base_url 为内部推理端点
# 4. 启动(3A: 自建基础设施)
AF_VERSION=1.0.0 docker compose -f deploy/docker-compose.intranet.yml --profile infra up -d
# 5. 创建管理员
docker compose -f deploy/docker-compose.intranet.yml exec backend \
python scripts/create_admin.py admin --password <your-password>
环境变量完整参考
所有应用级变量使用 ARTIFACTFLOW_ 前缀(通过 Pydantic Settings 自动映射),定义在 src/config.py。
核心
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_DEBUG |
false |
调试模式(详细日志 + 错误信息不脱敏 + 启用 Swagger 文档) |
JWT 认证
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_JWT_SECRET |
— (必填) | HS256 签名密钥 |
ARTIFACTFLOW_JWT_ALGORITHM |
HS256 |
签名算法 |
ARTIFACTFLOW_JWT_EXPIRY_DAYS |
7 |
Token 有效期(天) |
数据库
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_DATABASE_URL |
— (必填) | 连接串,如 sqlite+aiosqlite:///data/artifactflow.db 或 postgresql+asyncpg://... |
ARTIFACTFLOW_DATABASE_URLS |
"" |
逗号分隔多地址列表,启用 primary-first failover(按顺序尝试,首个可连即用);非空时优先于 DATABASE_URL,所有地址必须同一 driver(MySQL 或 PostgreSQL) |
ARTIFACTFLOW_DATABASE_POOL_SIZE |
5 |
连接池大小 |
ARTIFACTFLOW_DATABASE_MAX_OVERFLOW |
10 |
连接池溢出上限 |
ARTIFACTFLOW_DATABASE_POOL_TIMEOUT |
30 |
获取连接超时(秒) |
ARTIFACTFLOW_DATABASE_POOL_RECYCLE |
300 |
连接回收周期(秒) |
Redis
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_REDIS_URL |
"" |
空 = InMemory 回退;非空 = Redis 模式 |
ARTIFACTFLOW_REDIS_CLUSTER |
false |
Redis Cluster 模式 |
ARTIFACTFLOW_REDIS_KEY_PREFIX |
"" |
Key 命名空间前缀(启用 Redis 时必填) |
ARTIFACTFLOW_REDIS_MAX_CONNECTIONS |
50 |
连接池上限 |
ARTIFACTFLOW_LEASE_TTL |
90 |
对话租约 TTL(秒),心跳每 TTL/3 续租 |
SSE 与执行超时
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_SSE_PING_INTERVAL |
15 |
心跳间隔(秒),保持连接活跃 |
ARTIFACTFLOW_EXECUTION_TIMEOUT |
1800 |
总执行上限(秒),含 permission 等待 |
ARTIFACTFLOW_STREAM_CLEANUP_TTL |
60 |
执行结束后 stream 清理窗口(秒) |
ARTIFACTFLOW_PERMISSION_TIMEOUT |
300 |
单次权限等待超时(秒) |
Compaction 与上下文
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_COMPACTION_TOKEN_THRESHOLD |
60000 |
单次 LLM 调用 input+output 超此值时,引擎内立即触发 compaction |
ARTIFACTFLOW_COMPACTION_TIMEOUT |
120 |
单次 compact LLM 调用的超时(秒) |
ARTIFACTFLOW_INVENTORY_PREVIEW_LENGTH |
200 |
Artifact 清单预览截断长度 |
旧版本的
COMPACTION_PRESERVE_PAIRS/CONTEXT_MAX_TOKENS/TRUNCATION_PRESERVE_AI_MSGS已随异步后台 compaction 与 token-预算截断一起移除。现在引擎不做独立截断,压缩完全由上述阈值驱动(详见 engine.md → Compaction 机制)。
CORS
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_CORS_ORIGINS |
["http://localhost:3000"] |
允许的跨域来源 |
ARTIFACTFLOW_CORS_ALLOW_CREDENTIALS |
true |
允许携带凭证 |
ARTIFACTFLOW_CORS_ALLOW_METHODS |
["*"] |
允许的 HTTP 方法 |
ARTIFACTFLOW_CORS_ALLOW_HEADERS |
["*"] |
允许的请求头 |
其他
| 变量 | 默认值 | 说明 |
|---|---|---|
ARTIFACTFLOW_MAX_CONCURRENT_TASKS |
10 |
最大并发引擎执行数 |
ARTIFACTFLOW_MAX_UPLOAD_SIZE |
20971520 |
上传大小限制(字节,默认 20MB) |
ARTIFACTFLOW_DEFAULT_PAGE_SIZE |
20 |
分页默认每页条数 |
ARTIFACTFLOW_MAX_PAGE_SIZE |
100 |
分页最大每页条数 |
LLM 与工具 API Key
以下变量不使用 ARTIFACTFLOW_ 前缀,由 LiteLLM / 工具直接读取:
| 变量 | 说明 |
|---|---|
DASHSCOPE_API_KEY |
通义千问 API(默认模型必填) |
OPENAI_API_KEY |
OpenAI API |
DEEPSEEK_API_KEY |
DeepSeek API |
BOCHA_API_KEY |
Bocha Web 搜索 |
JINA_API_KEY |
Jina Reader(网页抓取) |
启动校验规则
应用启动时会验证以下条件,不满足则拒绝启动:
ARTIFACTFLOW_JWT_SECRET必须设置ARTIFACTFLOW_DATABASE_URL或ARTIFACTFLOW_DATABASE_URLS必须设置- 启用 Redis(
ARTIFACTFLOW_REDIS_URL非空)时,ARTIFACTFLOW_REDIS_KEY_PREFIX必须设置
运维参考
数据库迁移
容器启动时 deploy/entrypoint.sh 自动处理迁移:
flowchart TD
Start[容器启动] --> Check{数据库类型?}
Check -->|SQLite / 未配置| Skip[跳过迁移]
Check -->|PostgreSQL / MySQL| Lock{获取 PG advisory lock}
Lock -->|获取成功 Leader| Migrate[执行 alembic upgrade head]
Lock -->|获取失败 Follower| Wait[等待 lock 释放]
Migrate -->|成功| Release[释放 lock]
Migrate -->|失败| Exit1[退出, 不释放 lock]
Wait --> Verify{验证 schema at head?}
Verify -->|是| Continue[继续启动]
Verify -->|否| Exit2[退出 Leader 迁移失败]
Release --> Continue
Skip --> Continue
Continue --> Server[启动服务]
- 多副本安全: 通过
pg_advisory_lock(hashtext('alembic_migrate'))保证只有一个副本执行迁移 - 失败处理: Leader 迁移失败后不释放 lock(连接关闭自动释放),Follower 检测到 schema 未到 head 后退出,容器 restart policy 会重试
- Fallback: 如果 advisory lock 不可用(如 MySQL),直接执行
alembic upgrade head
Nginx 配置
生产模式使用 Nginx 反向代理(配置文件:deploy/nginx.conf):
- SSE 流式连接:
/api/v1/stream/路径关闭proxy_buffering,超时 1800s - Swagger 文档:生产环境下
/docs、/redoc、/openapi.json返回 404 --scale支持:使用 Docker 内部 DNS resolver127.0.0.11
健康检查
| 端点 | 用途 | 检查内容 |
|---|---|---|
GET /health/live |
存活探测(Mode 1 / K8s liveness) | 进程存活,始终返回 200 |
GET /health/ready |
就绪探测(Mode 2/3 / K8s readiness) | 进程 + DB + Redis 连通性,失败返回 503 |
数据卷
| 卷名 | 用途 |
|---|---|
artifactflow_data |
SQLite 数据库 / 上传文件 |
postgres_data |
PostgreSQL 数据(Mode 2A/3A) |
redis_data |
Redis AOF 持久化(Mode 2A/3A) |
停止与清理
--profile infra必须与启动时一致,否则 PG/Redis 容器不在 Compose 作用域内,down会跳过它们。
# Mode 1
docker compose down
# Mode 2A(启动时带了 --profile infra,停止也必须带)
docker compose -f docker-compose.prod.yml --profile infra down
# Mode 2B(无 --profile)
docker compose -f docker-compose.prod.yml down
# Mode 3A
docker compose -f deploy/docker-compose.intranet.yml --profile infra down
# Mode 3B
docker compose -f deploy/docker-compose.intranet.yml down
如需同时删除数据卷(不可逆,会丢失数据库和 Redis 数据):