部署文档
拉代码 → 配 .env → docker compose up,三步把平台跑起来。数据库不用单独安装,Compose 自带 PostgreSQL 和 Redis。每个配置字段的完整说明见 环境变量清单,本页不重复。
1. 准备要求
- Docker 20+ 与 Docker Compose v2。
- 2 核 4G 内存起步;磁盘预留 10G+(镜像 + 数据卷)。
- 端口:
3006(Web 入口,可自行改映射)、8003(节点控制服务,只对节点和内网开放,不是网页)、8004(Tunnel Runtime,仅容器内网,不对外)。 - PostgreSQL 16 与 Redis 7 由 Compose 自动创建,无需预装。
2. 拉取代码与子模块
克隆时带 --recurse-submodules,一条命令连主仓和五个子仓一起拉下来。不要只看主仓页面上的“关联仓库”——Git 实际拉取的是主仓 .gitmodules 记录的五个子仓。
# 1. 主仓 + 全部子模块(国内直连 GitHub 慢,用 gh-proxy 加速)
git clone --recurse-submodules https://gh-proxy.org/https://github.com/wuxin-gh/ai-lubricant.git
cd ai-lubricant
# 2. 确认五项前面没有 “-”
git submodule status
主仓使用相对 submodule URL,从 Gitee 克隆时会按当前组织解析为以下仓库:
| 目录 | Gitee 仓库 | 构建用途 |
|---|---|---|
node_server | xiongrun/ai-lubricant-node-server | 节点控制服务 |
nodes | xiongrun/ai-lubricant-nodes | 节点二进制与 Agent 运行时 |
user-frontend | xiongrun/ai-lubricant-user-frontend | Web 管理端与用户门户 |
mobile | xiongrun/ai-lubricant-mobile | 手机客户端(服务端部署本身可不构建) |
device-control | xiongrun/ai-lubricant-device-control | Android/iOS 控制组件 |
git submodule update 仍会失败。失败时先看命令输出的是哪个仓库 404/无权限,不要直接继续构建。3. 配置 .env
cp .env.example .env
最小必改项(其余字段保持默认即可启动):
| 变量 | 说明 |
|---|---|
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DATABASE | 同时是 Compose 建库参数和应用连接参数,一处改两边生效。密码必须换成强密码。 |
AI_LUBRICANT_COMPAT_ENABLED | 要用 Web 管理端(/manager)和用户门户(/console)必须设 true。 |
AI_LUBRICANT_BOOTSTRAP_ADMIN_EMAIL / _PASSWORD | 首次启动幂等创建平台管理员;创建完成后从 .env 移除明文密码。 |
NODE_CONTROL_TOKEN | 数据服务→控制服务的内部 Bearer,两进程必须同值。见下方「生成三个共享密钥」。 |
NODE_CREDENTIAL_ENCRYPTION_KEY | 节点 TOTP 凭据 AES-256 密钥,生成后不可轮换,否则已加密的节点凭据全部失效。见下方生成方式。 |
AGENT_ATTACHMENT_SIGNING_KEY | Agent 附件签名临时 URL 的 HMAC 密钥,多实例必须同值。见下方生成方式。 |
生成三个共享密钥(插入 .env,容器创建前必须有值)
容器创建时才会解析 .env,所以这三个值必须在 docker compose up 之前就写进 .env。任选一种生成方式(不需要 Python):
# a) 有 openssl(Linux/macOS 自带):
openssl rand -base64 32 → 填入 NODE_CONTROL_TOKEN=
openssl rand -hex 32 → 填入 NODE_CREDENTIAL_ENCRYPTION_KEY=
openssl rand -base64 48 → 填入 AGENT_ATTACHMENT_SIGNING_KEY=
# b) 有 Python:
python script/init_compose_env.py # 自动写入 .env,幂等
# c) 都没有:浏览器搜 “random hex generator”,生成 32 字节随机串填入即可
# 三个值互相独立、各不相同;系统不校验格式,任意随机串均可。
./.env:/app/.env)上文件重命名会报 [Errno 16] Device or resource busy,导致控制服务直接拒启(容器 unhealthy)。先在宿主 .env 填好非空值,node-server 读到值就跳过写回,不会触发该错误。docker compose restart 只重启进程,不重新解析 env_file——容器环境变量是创建那一刻的快照,之后改 .env 一个字节都不会进容器。改密钥后请用 docker compose up -d --force-recreate(或带 --build)。15432、Redis 到 6479,仅本机调试用;生产环境把它们从对外映射里去掉,只留内网。4. 启动
docker compose up -d --build
# 五个服务应为 running / healthy
docker compose ps
# 看数据服务日志
docker compose logs -f ai-lubricant
首次启动要构建应用镜像,需要几分钟。应用自动通过 postgres、redis 服务名连依赖,不需要手工填容器 IP。
| 服务 | 角色 | 端口 |
|---|---|---|
postgres | 业务数据库(渠道、账号、Key、任务、日志元数据) | 宿主 15432 → 容器 5432,仅调试 |
redis | 运行态真相源(限流、配额、冷却、会话) | 宿主 6479 → 容器 6379,仅调试 |
ai-lubricant | 数据服务:对外 API、管理端、用户门户、Agent 运行时、MCP | 宿主 3006 → 容器 8001 |
node-server | 节点控制面,接收节点 h2c 主动连接 | 宿主 8003 → 容器 8003 |
tunnel-server | Tunnel Runtime:管理 frpc / cloudflared / npc 子进程 | 容器 8004,不对外发布 |
三个应用服务共享同一个镜像(build 一次,靠 command 区分入口),并读同一份 .env。启动顺序由 depends_on + 健康检查串起来:postgres/redis → node-server → ai-lubricant / tunnel-server。
docker compose up -d postgres redis node-server ai-lubricant 即可,隧道方案管理页与任务预览端口对外暴露会不可用,其余功能不受影响。也可以用 TUNNEL_RUNTIME_ENABLED=false 让它空转。5. 初始化数据库
docker compose exec ai-lubricant python server/init_db.py
脚本幂等,重复运行安全。它只建表结构;如果启动日志提示「缺少必填主配置」,先完成管理员引导和基础配置,不要用反复重启解决。路径带 server/,脚本不在仓库根。
6. 访问
- Web 入口:
http://127.0.0.1:3006;管理端/manager,用户门户/console。 8003是节点控制服务,只接受节点连接和内部调用,不要当网页访问。- 生产部署用 HTTPS 反向代理指向
3006,并按 生产安全清单收敛其余端口。
7. 日常运维
# 升级到最新版
git pull
git submodule sync --recursive
git submodule update --init --recursive
docker compose up -d --build
# 备份数据库(逻辑备份)
docker compose exec -T postgres \
pg_dump -U ai_lubricant -d ai-lubricant -Fc > ai-lubricant.dump
# 停止(保留数据卷)
docker compose down
git pull 主仓,node_server/ 等子模块的工作树仍停在旧代码,docker compose up --build 用的还是旧源码。已部署升级后若节点页报「未配置控制面」,先 git submodule update --init --recursive 再重建镜像。docker compose down -v。8. 可选:ClickHouse
export CLICKHOUSE_REQUEST_PAYLOAD_ENABLED=true
docker compose --profile clickhouse up -d
不开也不影响模型代理主链路;开了才有请求大字段双写和对话存储。捕获请求正文前先完成隐私评估。
9. 替代方式:手动构建镜像
已有外部 PostgreSQL / Redis,或需要单独控制两个进程时才用这种方式;一般部署用上面的 Compose 即可。
# 构建镜像(python:3.11-slim + requirements.txt)
docker build -t ai-lubricant-api .
# 数据服务:外部 PG/Redis 地址用 -e 注入
docker run -d --name ai-lubricant \
-p 8001:8001 --env-file .env \
-e POSTGRES_HOST=10.x.x.x -e POSTGRES_PORT=5432 \
-e POSTGRES_USER=... -e POSTGRES_PASSWORD=... -e POSTGRES_DATABASE=ai-lubricant \
-e REDIS_HOST=10.x.x.x -e REDIS_PORT=6379 \
ai-lubricant-api
# 节点控制服务:同一镜像换启动命令
docker run -d --name ai-lubricant-node-server \
-p 8003:8003 --env-file .env \
-e POSTGRES_HOST=10.x.x.x -e POSTGRES_PORT=5432 \
-e POSTGRES_USER=... -e POSTGRES_PASSWORD=... -e POSTGRES_DATABASE=ai-lubricant \
-e REDIS_HOST=10.x.x.x -e REDIS_PORT=6379 \
-e NODE_CONTROL_HOST=0.0.0.0 -e NODE_CONTROL_PORT=8003 \
ai-lubricant-api python -m node_server
# Tunnel Runtime:同一镜像再换启动命令
docker run -d --name ai-lubricant-tunnel-server \
-p 8004:8004 --env-file .env \
-e POSTGRES_HOST=10.x.x.x -e POSTGRES_PORT=5432 \
-e POSTGRES_USER=... -e POSTGRES_PASSWORD=... -e POSTGRES_DATABASE=ai-lubricant \
-e REDIS_HOST=10.x.x.x -e REDIS_PORT=6379 \
-e AGENT_COMPOSE_BASE_URL=http://ai-lubricant-node-server:8003 \
-e TUNNEL_RUNTIME_HOST=0.0.0.0 -e TUNNEL_RUNTIME_PORT=8004 \
-e TUNNEL_RUNTIME_ENABLED=true \
ai-lubricant-api python -m tunnel_server
NODE_CONTROL_TOKEN 是数据服务→控制服务的内部 Bearer,两边必须完全一致,且必须在启动前就写进 .env(见第 3 步「生成三个共享密钥」)。不要依赖控制服务自动生成回写:单文件挂载的 .env 上写回会因文件重命名报 EBUSY 而拒启。Tunnel Runtime 经 AGENT_COMPOSE_BASE_URL 调控制服务,URL 错就启停不了隧道。完整 Web 前端需要先构建产物:cd user-frontend && pnpm install && pnpm build,再把 /api、/admin、/v1、/agent、/mcp 前缀反代到数据服务(支持 WebSocket 与 SSE)。仓库用 pnpm(pnpm-lock.yaml 锁定),不要换成 npm。
10. 生产上线清单
- 只公开 HTTPS 入口;PG、Redis、ClickHouse 和 8003 放内网或限制来源。
- 启用 API Key 鉴权,创建最小权限 key,并定期轮换。
- 为 PostgreSQL、Redis 数据、.env/Secrets、节点主密钥制定备份与恢复演练。
- 升级前备份数据库;先在预发布环境验证流式 API、管理端、MCP、WebSocket、节点连接。
- 保留前一版本镜像和前端 dist;回滚时判断数据库变更是否向后兼容,不能只回滚容器。
- 数据服务日志按日写入
logs/并保留 30 天;生产同步到集中日志平台并控制访问权限。 - 切换控制服务:先停旧控制进程再启新进程,绝不让两个 Registry 同时对同一批节点下发命令。
- 不要把请求 payload 捕获当默认选项;开启前评估隐私、脱敏、保留期和访问审计。