跳转到内容

使用 Docker 部署

Chorus 提供了官方 Docker 镜像 chorusaidlc/chorus-app。本指南包括:两种 Compose 形态, 即独立(内置数据库)与生产(外部 PostgreSQL + Redis);一个对接现有数据库的 docker run 示例;完整的环境变量参考;以及容器启动时的行为。

先拉取镜像:

Terminal window
docker pull chorusaidlc/chorus-app:latest

关于如何在独立与生产两种形态之间做选择,请参见部署概览。

无需外部数据库。镜像内置了 PGlite(嵌入式 PostgreSQL),并会自动启动 所需的一切。数据保存在 Docker 卷中,可在容器重启后持久保留。

创建 docker-compose.local.yml:

# Standalone Chorus — embedded PGlite, no external PostgreSQL or Redis
services:
app:
image: chorusaidlc/chorus-app:latest
ports:
- "8637:8637"
environment:
# No DATABASE_URL — entrypoint auto-starts embedded PGlite
- REDIS_URL=
# Leave empty: the container generates a random session secret on first
# start and keeps it in the chorus-local-data volume. Set it explicitly
# (openssl rand -base64 32) if you prefer to manage it yourself.
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-}
- COOKIE_SECURE=false
- DEFAULT_USER=${DEFAULT_USER:-admin@example.com}
- DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-changeme}
volumes:
- chorus-local-data:/app/data
volumes:
chorus-local-data:

然后运行:

Terminal window
docker compose -f docker-compose.local.yml up -d

打开 http://localhost:8637,使用 admin@example.com / changeme 登录(或通过 DEFAULT_USER / DEFAULT_PASSWORD 环境变量覆盖)。

独立部署示例使用 admin@example.com / changeme 启用旧版 Default Auth,共享访问前务必替换。下文生产 Compose 和 docker run 示例也显式启用了这个演示入口;仓库的生产 Compose 文件则默认将两个凭据留空,除非另行提供。使用托管本地账号时,注入超级管理员凭据并按下文设置,不要把演示登录当作托管的团队账号。

在独立模式下,容器会:

  • 在内部端口(5433)上启动 PGlite,不对外暴露。
  • 将数据存放在 chorus-local-data Docker 卷中,因此可在重启后持久保留。
  • 当 NEXTAUTH_SECRET 留空时,在首次启动时生成一个随机的会话签名密钥并保存在同一个卷中(参见 会话密钥)。
  • 禁用 Redis(回退到进程内的内存事件总线,仅支持单实例)。
  • 在启动时自动执行 Prisma 迁移。

面向生产环境,尤其是多副本部署时,请将应用对接到外部 PostgreSQL 与 Redis。创建 docker-compose.yml:

services:
app:
image: chorusaidlc/chorus-app:latest
ports:
- "8637:8637"
environment:
- DATABASE_URL=postgresql://chorus:chorus@db:5432/chorus
- REDIS_URL=redis://default:chorus-redis@redis:6379
# Session-signing secret. Leave empty and the container generates one on
# first start and persists it in the chorus-app-data volume (single
# replica only). For production, or more than one app container, set it
# explicitly in .env or the environment: openssl rand -base64 32
# Changing the secret invalidates Default Auth, local-account and Super Admin sessions.
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-}
- COOKIE_SECURE=${COOKIE_SECURE:-false}
- DEFAULT_USER=admin@example.com
- DEFAULT_PASSWORD=your-password
volumes:
- chorus-app-data:/app/data
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
redis:
image: redis:7-alpine
command: redis-server --requirepass chorus-redis
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "chorus-redis", "ping"]
interval: 5s
timeout: 3s
retries: 5
db:
image: postgres:17-alpine
environment:
POSTGRES_USER: chorus
POSTGRES_PASSWORD: chorus
POSTGRES_DB: chorus
volumes:
- chorus-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U chorus -d chorus"]
interval: 5s
timeout: 5s
retries: 5
volumes:
chorus-app-data:
chorus-data:
redis-data:

如果想自己提供会话密钥,请在启动前生成一次,写进 compose 文件旁边的 .env:

Terminal window
echo "NEXTAUTH_SECRET=$(openssl rand -base64 32)" >> .env

然后运行:

Terminal window
docker compose up -d

打开 http://localhost:8637,使用你在 DEFAULT_USER / DEFAULT_PASSWORD 中设置的凭据 登录。

如果你已经有 PostgreSQL 和 Redis 在运行,可直接启动容器:

Terminal window
docker run -d \
-p 8637:8637 \
-e DATABASE_URL=postgresql://user:pass@your-db-host:5432/chorus \
-e REDIS_URL=redis://default:password@your-redis-host:6379 \
-v chorus-app-data:/app/data \
-e COOKIE_SECURE=false \
-e DEFAULT_USER=admin@example.com \
-e DEFAULT_PASSWORD=your-password \
chorusaidlc/chorus-app:latest

此示例将生成的密钥保存在 chorus-app-data 中,容器重建后仍可复用。 若自行管理密钥,请注入持久的 NEXTAUTH_SECRET,并在每次启动时复用同一值。

变量说明
DATABASE_URLPostgreSQL 连接字符串。格式:postgresql://user:password@host:port/dbname。也可以改为设置单独的 DB_* 变量(见下文)。若省略,入口脚本会自动启动一个嵌入式 PGlite 实例。
NEXTAUTH_SECRET用于签发会话令牌的密钥。请使用随机字符串(例如 openssl rand -base64 32)。在 Docker 中可以留空:容器会在首次启动时生成一个并保存在 /app/data/.secret。运行多个应用容器时,必须在每个副本上显式设置同一个值。参见会话密钥。

数据库(DATABASE_URL 的替代方案)

Section titled “数据库(DATABASE_URL 的替代方案)”

若未设置 DATABASE_URL,入口脚本会用以下单独变量拼装它:

变量说明
DB_HOSTPostgreSQL 主机
DB_PORTPostgreSQL 端口(默认:5432)
DB_USERNAMEPostgreSQL 用户名
DB_PASSWORDPostgreSQL 密码
DB_NAME数据库名

Redis 通过独立连接提供跨实例 SSE 和共享认证计数器。非空 REDIS_URL 优先;否则 REDIS_HOST 使用 TLS(rediss),端口默认 6379、用户名默认 default,用户名在提供 REDIS_PASSWORD 时使用。非 TLS Redis 应显式使用 redis://。只有 URL 和 host 均未配置时,事件和限流才完全留在进程内。Redis 故障会启用每进程备用限流,不再共享额度,也不会阻止全部登录;意外的限流器错误可能放行。具体限制和恢复行为参见共享认证限流。

变量说明
REDIS_URL完整的 Redis 连接字符串。格式:redis://username:password@host:port。优先级高于以下单独变量。
REDIS_HOSTRedis 主机(在未设置 REDIS_URL 时使用)
REDIS_PORTRedis 端口(默认:6379)
REDIS_USERNAMERedis 用户名(默认:default)
REDIS_PASSWORDRedis 密码

托管本地账号保存在数据库中,不通过 DEFAULT_USER / DEFAULT_PASSWORD 配置。向应用注入 SUPER_ADMIN_EMAIL 和 SUPER_ADMIN_PASSWORD_HASH,再从管理面板创建本地账号工作区并邀请首位工作区管理员。无需身份提供商或邮件服务。同一工作区的本地账号与 OIDC 互斥,已有工作区不可转换。持久化 NEXTAUTH_SECRET 并在所有副本间共享;共享访问使用 HTTPS 和 COOKIE_SECURE=true。设置账号以及如何只关闭旧版 Default Auth 参见运维指南。

AUTH_TRUST_PROXY 默认关闭,仅 true 启用。AUTH_TRUST_PROXY_HOPS 默认 1,有效值为 1 到 16 的整数,从 X-Forwarded-For 右侧计数。只有代理链强制执行且不可绕过时才启用信任,HTTPS 本身不足以建立信任。内置 CDK 的 ALB 模式使用 true / 1,CloudFront 模式使用 false / 2,因为 VPC 流量仍可绕过 CloudFront 到达私有源站。

变量说明
DEFAULT_USER可选的旧版 Default Auth 邮箱,需同时设置 DEFAULT_PASSWORD。按需创建用户和工作区,不会创建托管本地账号或授予本地工作区管理员角色。
DEFAULT_PASSWORD旧版 Default Auth 的明文密码,运行时直接比较,并非 bcrypt 比对。与数据库中的本地账号密码无关。
NEXTAUTH_URL应用对外的基础 URL(默认:http://localhost:8637)。在反向代理后运行时请设置此项。
COOKIE_SECURE设为 "false" 可为纯 HTTP 部署禁用安全 Cookie(docker-compose 中默认为 "false")。以 HTTPS 部署到生产环境时设为 "true"。
变量默认值说明
LOG_LEVELinfo(生产)/ debug(开发)服务端最低日志级别。可选:trace、debug、info、warn、error、fatal、silent。设为 info 可抑制 Prisma 查询日志。
NEXT_PUBLIC_LOG_LEVELwarn(生产)/ debug(开发)浏览器端最低日志级别。可选:debug、info、warn、error。

生产 Docker 镜像始终将 JSON 输出到 stdout(可直接对接 CloudWatch / ELK)。彩色美化输出仅在 本地开发时可用。

变量说明
SUPER_ADMIN_EMAIL超级管理员账号的邮箱(可访问 /admin 面板)。
SUPER_ADMIN_PASSWORD_HASH超级管理员密码的 bcrypt 哈希。生成方式:node -e "console.log(require('bcryptjs').hashSync('your-password', 10))"

容器的入口脚本每次启动都会执行相同的流程:

  1. 检查 NEXTAUTH_SECRET。若为空,或等于以前示例文件中出现过的占位值,容器会在 /app/data/.secret 中读取或生成密钥,并在日志中说明做了什么(但绝不打印密钥本身)。你自己 显式设置的密钥会原样使用。
  2. 若未设置 DATABASE_URL 且未提供任何 DB_* 变量,入口脚本会在内部端口(5433)上启动 一个嵌入式 PGlite 实例。当已配置外部数据库时,不会启动 PGlite。
  3. 执行 prisma migrate deploy,应用任何待处理的数据库迁移。
  4. 若数据库尚未就绪,每 10 秒重试一次(最多 30 次,约五分钟)。
  5. 迁移成功后,Next.js 服务在 8637 端口启动。

托管本地账号会话同样使用 NEXTAUTH_SECRET,轮换密钥也会使这些会话失效。

NEXTAUTH_SECRET 用于签发 Chorus 自己的会话 JWT(内置登录和超级管理员登录)。 OIDC 令牌由身份提供方签名,智能体 API 密钥也单独校验。轮换此密钥会使 Chorus 自签名会话失效, 不会轮换 API 密钥,也不会使身份提供方的 OIDC 令牌失效。

  • 显式设置非占位值:直接使用,不读写密钥文件。
  • 未设置、为空或使用已知公开占位值:复用 /app/data/.secret;文件不存在或为空时, 生成 32 个随机字节,编码为 64 个十六进制字符,以 0600 权限保存。环境变量中的占位值还会触发警告。
  • 持久化密钥不可用:文件不是普通文件、不可读、保存了公开占位值,或生成、写入失败时, 容器会在迁移前停止。已保存的公开占位值不会被悄悄接受或替换。

日志不会打印密钥值。要保留自动生成的密钥,请把 /app/data 放在持久卷上。多副本部署必须向每个实例显式注入 同一个密钥;AWS CDK 栈已通过 Secrets Manager 共享该值。

用 openssl rand -base64 32 生成一次,存入部署的密钥库或受保护的 .env,后续启动复用。 有效密钥改变后,内置邮箱/密码登录的用户和超级管理员需要重新登录。删除 .secret 只会影响自动生成的密钥; 已显式配置密钥时,删除该文件不会轮换密钥。

Docker 入口脚本和 npm chorus 启动器会自动处理密钥。直接用 next start 或 node server.js 启动时不会自动生成,需自行配置安全密钥。应用遇到已知占位值时会记录错误,但不会替换该值; 未设置密钥时,无法签发 Chorus 自签名会话。

  • 基础镜像: node:22-alpine
  • 内部端口: 8637
  • 架构: linux/amd64、linux/arm64
  • 在本机自托管:基于 PostgreSQL 17 的 install.sh 本地安装、可选的 局域网 HTTPS 或 Cloudflare Tunnel,以及 PG16 到 PG17 的迁移。
  • 生产环境部署:从全局 npm 包运行,以及完整的 AWS CDK 演练。
  • 运维自托管的 Chorus:首次登录引导、部署侧身份认证,以及升级前的 备份。