跳到主要内容

快速部署

本页带你在 5 分钟内用 Docker Compose 拉起一套完整的 Aivory 生产栈:PostgreSQL、Redis、Qdrant、内置代码沙箱,以及一个同时伺服前端 SPA 和 /api 后端的 app 容器(二者同源,无需任何域名或 CORS 配置)。

整套栈由一份 compose 文件描述,包含以下服务:

服务镜像作用
postgrespostgres:16-alpine关系型存储:用户、对话、知识库、用量等
redisredis:7-alpine缓存、限流计数器、跨进程停止流式输出的 pub/sub
qdrantqdrant/qdrant:v1.12.4RAG 向量检索
sandboxghcr.io/hjxwz123/aivory-sandbox-sidecar内置代码执行沙箱,仅内网可达
appghcr.io/hjxwz123/aivory-app单容器同源伺服 SPA 与 /api
不想跑完整栈?

Aivory 的后端按环境变量自动选型:不配 PostgreSQL 就用内嵌 SQLite,不配 Redis 就用进程内缓存,不配 Qdrant 则 RAG 回退为全文注入。想用最小依赖跑单机,见 SQLite 模式。本页描述的是推荐的完整生产部署。

前置要求

项目要求
Docker Engine已安装并可正常运行(docker info 无报错)
Docker Composev2(docker compose 子命令,不是旧版 docker-compose)
机器规格2 核 CPU + 4 GB 内存起步
端口宿主机 80 端口空闲(可改,见下文)
磁盘数据库、向量、上传文件均持久化在本机,按使用量预留
沙箱需要 Docker socket

内置代码沙箱通过挂载的 /var/run/docker.sock 在宿主机上派生每会话的隔离容器,因此宿主机必须能直接运行 Docker(不适用于无 Docker 守护进程的托管容器平台)。沙箱服务不发布任何宿主端口,只在私有网络内被 app 访问。

第 1 步:获取代码

git clone https://github.com/hjxwz123/Aivory.git
cd Aivory/deploy

部署相关的全部文件都在 deploy/ 目录下:docker-compose.prod.yml.env.example

第 2 步:创建并编辑 .env

cp .env.example .env

.env必须修改的只有三项,其余全部可以保持默认。三项都留着占位值会导致启动失败或严重安全问题:

# 生成三个强随机值
openssl rand -hex 24 # 用作 POSTGRES_PASSWORD
openssl rand -hex 24 # 用作 REDIS_PASSWORD
openssl rand -hex 32 # 用作 JWT_SECRET
变量要求说明
POSTGRES_PASSWORD必设PostgreSQL 密码。不设置时 compose 直接拒绝启动
REDIS_PASSWORD必设Redis 密码。不设置时 compose 直接拒绝启动
JWT_SECRET必设,长度至少 32 字符签发登录令牌的密钥。生产环境下 Aivory 检测到占位值或过短密钥会拒绝启动
JWT_SECRET 一旦泄露等于交出全部账号

请务必使用 openssl rand -hex 32 生成,不要用可猜测的字符串。同时注意:更换 JWT_SECRET 会使所有已登录会话失效。

模型服务商的 API Key(Anthropic / OpenAI / Gemini 等)不在 .env 里配置,它们存在数据库的渠道表中,部署完成后在管理后台添加,见首次运行配置

第 3 步:启动

方式一,拉取预构建镜像(推荐,来自 GitHub Container Registry):

docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d

方式二,本地从源码构建(在代码上做了修改,或官方镜像未覆盖你的 CPU 架构时):

docker compose -f docker-compose.prod.yml up -d --build
同一份 compose 文件支持两种方式

app 服务同时声明了 image:build::本地存在预构建镜像时 Compose 优先使用镜像,否则回退到本地构建。数据库 schema 由应用启动时自动迁移创建,不需要手动执行任何 SQL。

第 4 步:验证

docker compose -f docker-compose.prod.yml ps

预期看到 5 个服务:postgresredis 处于 healthy,qdrantapp 处于 running,sandbox 首次启动时需要先拉取沙箱运行时镜像,健康检查预留了 120 秒启动窗口,稍等即可变为 healthy

然后请求首页。app 容器内部监听 8787 端口,compose 默认把它映射到宿主机 80 端口:

curl -sI http://localhost

返回 HTTP/1.1 200 且内容为 SPA 页面即部署成功。如果你把端口映射改成了别的(例如 8080:8787),把命令里的端口对应替换。

80 端口被占用怎么办

端口映射不走环境变量,直接编辑 docker-compose.prod.ymlapp 服务的 ports 段,把 "80:8787" 的左边改掉(例如 "8080:8787"),右边的 8787 是容器内监听端口,不要改。

第 5 步:打开站点,进入首启设置

浏览器访问 http://<你的服务器 IP 或域名>。全新部署没有任何用户,页面会自动进入首启设置:你创建的第一个账号立即成为管理员。接下来的建号、添加渠道、创建模型等步骤,见首次运行配置

一条龙命令

以下命令块从零完成:克隆、生成密钥、写入 .env、拉镜像、启动。适合在一台全新机器上直接粘贴执行:

git clone https://github.com/hjxwz123/Aivory.git \
&& cd Aivory/deploy \
&& cp .env.example .env \
&& sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$(openssl rand -hex 24)|" .env \
&& sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -hex 24)|" .env \
&& sed -i "s|^JWT_SECRET=.*|JWT_SECRET=$(openssl rand -hex 32)|" .env \
&& docker compose -f docker-compose.prod.yml pull \
&& docker compose -f docker-compose.prod.yml up -d \
&& docker compose -f docker-compose.prod.yml ps
保存好 .env

上面的命令把随机密钥直接写进了 deploy/.env。这个文件等同于你部署的钥匙串,请纳入备份,不要提交到公开仓库。

.env.example 变量逐条说明

下面按 .env.example 中的分组逐条解释每个变量该不该改。

镜像来源

变量默认值该不该改
IMAGE_OWNERhjxwz123一般不改。只有当你 fork 了仓库并用自己的 GHCR 命名空间发布镜像时才改成自己的账号
IMAGE_TAGlatest一般不改。如需锁定版本,改为对应的镜像标签,避免 latest 漂移

网络与跨域

变量默认值该不该改
ALLOWED_ORIGINS未设置(注释状态)保持不设。单容器部署里 SPA 与 /api 同源,不存在跨域;仅当你把前端拆到与 API 不同的 origin 时才需要。域名与 HTTPS 见反向代理

注意:没有 WEB_PORTPUBLIC_ORIGIN 这类变量。宿主端口在 compose 文件里改;域名不需要配置,容器被哪个 host 访问,哪个 host 就能用,多个域名同时指向也可以。

PostgreSQL

变量默认值该不该改
POSTGRES_USERaivory不必改
POSTGRES_DBaivory不必改
POSTGRES_PASSWORD占位值必改,openssl rand -hex 24

Redis

变量默认值该不该改
REDIS_PASSWORD占位值必改,openssl rand -hex 24

Qdrant

变量默认值该不该改
QDRANT_URLhttp://qdrant:6333不必改。只有指向外部 Qdrant 集群时才覆盖
QDRANT_API_KEY可不改。留空时 qdrant 服务与 app 共用同一个内置内部密钥,开箱即用;Qdrant 不发布任何宿主端口,仅内网可达。想要独立强密钥可用 openssl rand -hex 24 覆盖

认证

变量默认值该不该改
JWT_SECRET占位值必改,openssl rand -hex 32,至少 32 字符,否则生产环境拒绝启动

数据目录与备份

变量默认值该不该改
DATA_DIR./data视磁盘规划而定。宿主机路径,绑定挂载到容器 /app/data,存放用户上传文件与生成产物,必须纳入备份
BACKUP_DIR/app/data/backups不必改。容器内路径,管理后台异步生成的全量迁移 ZIP 存放处,宿主机上对应 DATA_DIR/backups
MAX_BACKUP_BYTES21474836480(20 GiB)一般不改。管理后台导入备份的大小上限,含向量数据的全量包可能很大,超限时调大

数据库、Redis、Qdrant 的数据分别在命名卷 pgdataredisdataqdrantdata 中,备份策略见备份与迁移

演示模型

变量默认值该不该改
ENABLE_MOCK_PROVIDERfalse可选。设为 true 会注入一个内置演示渠道,不需要任何真实 API Key 就能端到端跑通对话,适合先验证部署;在管理后台添加真实渠道后改回 false

联网搜索(可选)

变量默认值该不该改
SEARCH_PROVIDER可选。搜索后端类型:serper / brave 需配 SEARCH_API_KEY;searxng 需配 SEARCH_BASE_URL,无需 key
SEARCH_API_KEYSEARCH_PROVIDER 而定
SEARCH_BASE_URLsearxng 类后端需要

这三项也可以部署后在管理后台在线配置,.env 里的值只是启动期兜底,可以先全部留空。

嵌入模型(可选,知识库检索质量相关)

变量默认值该不该改
EMBEDDING_BASE_URL建议生产配置。留空时使用内置 256 维本地 embedder,可用但检索质量不适合生产;指向任意 OpenAI 格式的 /v1/embeddings 端点即可
EMBEDDING_API_KEY随嵌入服务而定
EMBEDDING_MODELtext-embedding-3-small按你的嵌入服务改
EMBEDDING_DIM1536必须与嵌入模型的输出维度一致。Qdrant 按维度使用独立 collection,维度不匹配会退回本地 256 维 embedder

MinerU 文档解析(可选)

变量默认值该不该改
MINERU_API_URLhttps://mineru.net一般不改
MINERU_API_KEY可选。用于扫描版 / 图片型 PDF 的 OCR 解析;不配置时这类文档仍能上传进知识库,但内容只有一行占位文本。也可部署后在管理后台配置

代码沙箱(注释状态,通常什么都不用设)

沙箱服务随本栈一起启动,app 通过私有网络访问它,双方共享同一个内置默认密钥,开箱即用。仅在需要覆盖默认限额时取消注释:

变量默认值说明
SANDBOX_API_KEY内置共享默认值想用自定义密钥时设置,appsandbox 会同时读到
SANDBOX_MEMORY2g每个会话容器的内存上限
SANDBOX_CPUS1每个会话容器的 CPU 配额
SANDBOX_MAX_SESSIONS16并发沙箱会话数上限
SANDBOX_WORKSPACE_SIZE512m每会话 /workspace 大小
SANDBOX_NETWORKnone沙箱内代码默认无网络;确需联网时才改为 bridge

沙箱架构与安全边界详见代码沙箱部署。同时请保持管理后台设置里的 sandbox_base_url / sandbox_api_key 两个字段为空,这样内置沙箱才会生效。

下一步