Docker Compose 部署 Novu 指南

以官方 Docker Compose 形态从零部署 Novu 3.19.0 全家桶:双方案部署、端口规划、密钥生成、健康验证、数据持久化、备份与升级,命令回显全实测。

NovuNovu即时通信2026/10/21

Docker Compose 部署 Novu 指南

目标:在 Linux 服务器上以官方 Docker Compose 发行形态从零部署一套可用的 Novu 3.19.0(api/worker/ws/dashboard 四服务 + MongoDB + Redis),覆盖端口规划、密钥生成、健康验证、升级与备份。全部命令与回显已在 Ubuntu 22.04 服务器实测通过(实测版本 3.19.0;版本溯源与组件定位见 《Novu 3.19.0 介绍与选型指南》)。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • 软件版本:Novu 3.19.0(官方镜像 ghcr.io/novuhq/novu/api|worker|ws|dashboard:3.19.0)、MongoDB mongo:8.0.17、Redis redis:alpine
  • Docker:Docker Compose v5.5.1(docker compose v2 命令体系)
  • 实测端口规划:API 8148 → 容器 3000、WebSocket 8149 → 容器 3002、Dashboard 8150 → 容器 4000(宿主端口按本机空闲槽位选择,绑定前用 ss -ltnp 确认)
  • 部署目录:/opt/novu/(compose 文件与 .env 所在目录,可自定义)
  • 服务依赖:MongoDB(持久化主存储)、Redis(任务队列 db2);S3 兼容存储官方 compose 默认未内置服务,附件存储按需自备

二、镜像选型说明

Novu 官方不提供单体安装包,自托管发行形态就是 Docker Compose 全家桶。镜像来源与选型如下表(docker compose images 实测回显):

cd /opt/novu && docker compose images
CONTAINER           REPOSITORY                      TAG                 PLATFORM            IMAGE ID            SIZE                CREATED
api                 ghcr.io/novuhq/novu/api         3.19.0              linux/amd64         5cd2a586888b        2.4GB               2 months ago
dashboard           ghcr.io/novuhq/novu/dashboard   3.19.0              linux/amd64         15a7773e0165        402MB               2 months ago
mongodb             mongo                           8.0.17              linux/amd64         9814652e33f0        1.24GB              9 months ago
redis               redis                           alpine              linux/amd64         3811787313eb        160MB               4 weeks ago
worker              ghcr.io/novuhq/novu/worker      3.19.0              linux/amd64         2fa726519589        2.19GB              2 months ago
ws                  ghcr.io/novuhq/novu/ws          3.19.0              linux/amd64         00aa8b9f080d        2.12GB              2 months ago

关键选型结论:

  • Novu 四个业务镜像来自官方 GHCR(ghcr.io/novuhq/novu/api|worker|ws|dashboard),必须固定具体版本 tag(如 3.19.0),不要用 latest——官方 compose 文件本身就是按版本号锚定的;
  • MongoDB 用官方 mongo:8.0.17(官方 compose 指定版本);Redis 用 redis:alpine(官方 compose 原样,固定小版本可改为 redis:7.4-alpine 等,实测 alpine 当前对应 Redis 7.x 稳定线);
  • 架构支持 linux/amd64(上表 PLATFORM 列实测),ARM64 需自行确认官方镜像多架构可用性;
  • 镜像总体积约 8.5GB(含 Mongo/Redis),磁盘预留建议 15GB 以上。

三、前置条件

  1. 服务器已安装 Docker Engine 与 docker compose 插件,验证命令:
docker compose version
Docker Compose version v5.5.1
  1. 已安装 curl 与 openssl(官方 setup 脚本依赖;Ubuntu 22.04 默认自带);
  2. 端口空闲核验(绑定前必须实测,本例选 8148/8149/8150):
for p in 8148 8149 8150; do ss -ltn | grep ":$p " && echo "$p 被占用" || echo "$p 空闲"; done
8148 空闲
8149 空闲
8150 空闲
  1. 资源建议:官方 self-hosting 文档给出的单机基线为 Novu 全部服务 4 vCPU/8GB RAM、MongoDB 2GB RAM/20GB 磁盘、Redis 2GB RAM(队列实例开 AOF)。内存不足 8GB 时服务可启动但 workflow 执行会明显变慢;
  2. 国外镜像拉取受限的网络环境,为 Docker 守护进程配置 HTTP 代理后 docker compose pull 可正常走代理拉取 GHCR 镜像。

四、部署步骤

4.1 方案 A:官方一键脚本

官方为快速体验提供 setup 脚本,自动下载 compose 文件、生成三个安全密钥并启动全部服务:

# 下载并执行官方 setup 脚本(脚本源码:novu 仓库 next 分支 docker/community/setup.sh)
curl -fsSL https://raw.githubusercontent.com/novuhq/novu/next/docker/community/setup.sh | NOVU_DIR=/opt/novu bash

实测输出(3.19.0 实测首尾节选,中段为 6 个容器的 Creating/Starting/Waiting 逐行输出):

▸ Novu Self-Hosted Setup

▸ Downloading docker-compose.yml...
▸ Downloading .env.example...
▸ Created .env with secure random secrets

▸ Setup complete. Starting Novu...

 Container mongodb Creating
 Container redis Creating
 ...
 Container worker Healthy
 Container api Healthy
 Container dashboard Starting
 Container dashboard Started

▸ Novu is running:
  Dashboard : http://localhost:4000
  API       : http://localhost:3000
  WebSocket : http://localhost:3002

▸ View logs with: docker compose logs -f

脚本执行完即验证可用(实测回显,官方默认端口 3000):

curl -sS http://localhost:3000/v1/health-check
{"data":{"status":"ok","info":{"db":{"status":"up"},"workflowQueue":{"status":"up"},"apiVersion":{"version":"3.19.0","status":"up"}},"error":{},"details":{"db":{"status":"up"},"workflowQueue":{"status":"up"},"apiVersion":{"version":"3.19.0","status":"up"}}}}

脚本行为说明:NOVU_DIR 指定安装目录(默认 ./novu);若目标目录已有 .env,脚本只补齐缺失的密钥不覆盖已有配置;生成三个密钥 JWT_SECRET(openssl rand -hex 32)、STORE_ENCRYPTION_KEY(hex 16,必须恰好 32 字符)、NOVU_SECRET_KEY(hex 32)。

⚠️ 两个注意点(实测归纳):一是官方 compose 的容器名固定为 api/worker/ws/dashboard/mongodb/redis,同一台服务器上方案 A 与方案 B 不能同时存在,实测同机先起方案 B 再执行脚本时报 The container name "/mongodb" is already in use,二选一或改容器名;二是该方式使用官方默认端口 3000/3002/4000,与本机已占用端口冲突时需按 4.2 手动调整映射;脚本不注册为系统服务,重启后依赖 compose 的 restart: unless-stopped 策略随 Docker 守护进程自启。

4.2 方案 B:手动部署(可自定义端口,推荐生产)

4.2.1 建目录并下载官方文件

mkdir -p /opt/novu && cd /opt/novu
curl -fsSL https://raw.githubusercontent.com/novuhq/novu/next/docker/community/docker-compose.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/novuhq/novu/next/docker/community/.env.example -o .env.example

命令无输出即为成功,ls -la 确认两个文件已就位(回显节选):

-rw-r--r-- 1 root root 7267 docker-compose.yml
-rw-r--r-- 1 root root 2206 .env.example

4.2.2 修改 compose 端口映射与项目名

官方 compose 文件有两处必须按真实服务器环境调整:项目名(name:,用于多套环境隔离)与宿主端口映射。用编辑器打开 docker-compose.yml:

  1. 顶部 name: novu 改为唯一项目名(本例 novu-3190-stack,compose 项目名只允许小写字母数字与连字符,novu-3.19.0-stack 会被规范化为 novu-3190-stack);
  2. api 服务的端口段 ports: - ${API_PORT}:${API_PORT} 改为宿主固定映射 ports: - "8148:3000";
  3. ws 服务的 ports: - ${WS_PORT}:${WS_PORT} 改为 ports: - "8149:3002";
  4. dashboard 服务的 ports: - 4000:4000 改为 ports: - "8150:4000"。

⚠️ 端口映射必须显式写死宿主端口:官方写法 ${API_PORT}:${API_PORT} 会把 .env 里的 3000 同时用作宿主端口,与常见 Web 应用默认端口冲突的概率高。

4.2.3 编写 .env(密钥 + 对外地址)

cd /opt/novu && cp .env.example .env
# 生成三个必需密钥(各执行一次,值不可复用)
openssl rand -hex 32   # JWT_SECRET
openssl rand -hex 16   # STORE_ENCRYPTION_KEY(须恰好 32 字符)
openssl rand -hex 32   # NOVU_SECRET_KEY(即 API 调用侧的演示密钥来源,生产须替换)

实测生成值示例(本环境实测产出,读者应重新生成自己的值):

fade86f0d43ee13a31d528da5d1acfa41aeabddee5fa49e32b23ed2e54ad0105
b9c562f194b51df3054236f1a18de9af
a7629e5aa7faedfb7723e41c65ffe008673734968b25fbf4f5dfbe488ea6e8ab

编辑 .env,逐项改为实际值(完整参数语义见本专栏配置参数详解篇):

# 密钥三件套(上面 openssl 生成的值)
JWT_SECRET=fade86f0d43ee13a31d528da5d1acfa41aeabddee5fa49e32b23ed2e54ad0105
STORE_ENCRYPTION_KEY=b9c562f194b51df3054236f1a18de9af
NOVU_SECRET_KEY=a7629e5aa7faedfb7723e41c65ffe008673734968b25fbf4f5dfbe488ea6e8ab

# 对外主机名:本机访问写 http://localhost,服务器/公网写实际 IP 或域名
HOST_NAME=http://192.168.146.128

# MongoDB 管理口令(演示值;生产环境务必替换为强口令)
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=q1w2e3r4
MONGO_URL=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongodb:27017/novu-db?authSource=admin

# 对外地址改端口后,以下四项把 3000/4000/3002 换成实际宿主端口
VITE_API_HOSTNAME=${HOST_NAME}:8148
VITE_WEBSOCKET_HOSTNAME=${HOST_NAME}:8149
API_ROOT_URL=${HOST_NAME}:8148
FRONT_BASE_URL=${HOST_NAME}:8150

⚠️ HOST_NAME 是 dashboard 前端拼 API/WS 地址的根:写成浏览器不可达的值(如 http://localhost 而从远程访问)时,管理台会持续报接口不可达。VITE_* 与 FRONT_BASE_URL/API_ROOT_URL 必须与实际宿主端口一致,否则登录页能开但登录请求 404。

4.2.4 启动与就绪观察

cd /opt/novu && docker compose up -d

首次执行会拉取 6 个镜像(约 8.5GB,GHCR 走代理需数分钟),随后按依赖链(redis/mongodb → api/worker/ws → dashboard)逐个启动。就绪状态实测(docker compose ps):

NAME        IMAGE                                  COMMAND                   SERVICE     CREATED          STATUS                    PORTS
api         ghcr.io/novuhq/novu/api:3.19.0         "sh -c 'node dist/ma…"   api         13 minutes ago   Up 13 minutes (healthy)   0.0.0.0:8148->3000/tcp, [::]:8148->3000/tcp
dashboard   ghcr.io/novuhq/novu/dashboard:3.19.0   "/app/docker-entrypo…"   dashboard   13 minutes ago   Up 12 minutes (healthy)   0.0.0.0:8150->4000/tcp, [::]:8150->4000/tcp
mongodb     mongo:8.0.17                           "docker-entrypoint.s…"   mongodb     13 minutes ago   Up 13 minutes (healthy)   27017/tcp
redis       redis:alpine                           "docker-entrypoint.s…"   redis       13 minutes ago   Up 13 minutes (healthy)   6379/tcp
worker      ghcr.io/novuhq/novu/worker:3.19.0      "sh -c 'node dist/ma…"   worker      13 minutes ago   Up 13 minutes (healthy)
ws          ghcr.io/novuhq/novu/ws:3.19.0          "sh -c 'node dist/ma…"   ws          13 minutes ago   Up 13 minutes (healthy)   0.0.0.0:8149->3002/tcp, [::]:8149->3002/tcp

6 个服务全部 (healthy) 即部署成功。api 健康检查带 start_period: 40s,冷启动后 1-2 分钟内出现 healthy 属正常。

4.2.5 验证三端点

# API 健康检查
curl -sS http://192.168.146.128:8148/v1/health-check
{"data":{"status":"ok","info":{"db":{"status":"up"},"workflowQueue":{"status":"up"},"apiVersion":{"version":"3.19.0","status":"up"}},"error":{},"details":{"db":{"status":"up"},"workflowQueue":{"status":"up"},"apiVersion":{"version":"3.19.0","status":"up"}}}}
# WebSocket 服务健康检查
curl -sS http://192.168.146.128:8149/v1/health-check
{"status":"ok","info":{"webSocketsQueue":{"status":"up"},"db":{"status":"up"},"ws-server":{"status":"up"},"apiVersion":{"version":"3.19.0","status":"up"}},"error":{},"details":{"webSocketsQueue":{"status":"up"},"db":{"status":"up"},"ws-server":{"status":"up"},"apiVersion":{"version":"3.19.0","status":"up"}}}
# Dashboard 首页可达性与标题
curl -sS -o /dev/null -w 'HTTP %{http_code}\n' http://192.168.146.128:8150
curl -sS http://192.168.146.128:8150 | grep -oE '<title>[^<]+</title>'
HTTP 200
<title>Novu Cloud Dashboard</title>

浏览器打开 http://<服务器IP>:8150 进入注册页创建首个管理账号(自托管版仅支持邮箱+密码注册,密码策略要求至少 8 位且含大小写字母、数字与特殊字符,实测示例 Q1w2e3r4#)。API 侧的注册、认证与调用链路实测见本专栏 API 使用篇。

4.3 方案对比与选择

维度方案 A(官方脚本)方案 B(手动部署)
端口固定 3000/3002/4000宿主端口任意规划
密钥脚本自动生成自行 openssl 生成
可控性低(脚本行为黑盒)高(compose/.env 全显式)
适用本机快速体验生产/服务器部署

选择建议:本机体验用方案 A;任何需要自定义端口、纳入配置管理、多环境隔离的部署用方案 B。两方案的 compose 文件与 .env 结构完全一致,A 生成的目录可直接改为 B 的形态继续维护。

五、数据持久化说明

  • MongoDB 数据:compose 顶层声明 volumes: mongodb:,挂载到 mongodb 服务的 /data/db。这是 Novu 唯一的持久化主存储(workflow、subscriber、message、notification、preference 全部在内)。查看卷名与宿主落点:
docker volume ls | grep novu
local      novu-3190-stack_mongodb
docker volume inspect novu-3190-stack_mongodb --format '{{.Mountpoint}}'
/var/lib/docker/volumes/novu-3190-stack_mongodb/_data

卷名前缀即 compose 项目名,因此不同项目名的栈数据天然隔离。docker compose down 不删卷,docker compose down -v 会连同 MongoDB 数据一起删除——生产环境严禁对在线栈执行 down -v。

  • Redis:仅承载队列与缓存(默认 db2),任务丢失可由重试机制兜底,官方 compose 未给 Redis 配持久化卷;对消息可靠性要求高的部署建议为队列实例启用 AOF(改用带 --appendonly yes 的 redis 服务定义并加卷)。
  • 备份:用 mongodump 做逻辑备份(在 mongo 服务内执行,导出文件再拷出):
docker compose exec mongodb mongodump -u root -p q1w2e3r4 --authenticationDatabase admin --db novu-db --archive=/tmp/novu-db.archive
docker compose cp mongodb:/tmp/novu-db.archive /opt/novu/backup/novu-db-$(date +%F).archive

回显(实测节选,novu-db 共导出 42 个集合):

2026-10-21T14:28:30.740+0000    writing novu-db.messages to archive '/tmp/novu-db.archive'
2026-10-21T14:28:30.741+0000    writing novu-db.notifications to archive '/tmp/novu-db.archive'
2026-10-21T14:28:30.741+0000    done dumping novu-db.messages (3 documents)
2026-10-21T14:28:30.742+0000    done dumping novu-db.notifications (3 documents)

docker compose cp 的实测回显:

 mongodb Copying mongodb:/tmp/novu-db.archive to /opt/novu/backup/novu-db-2026-10-21.archive
 mongodb Copied mongodb:/tmp/novu-db.archive to /opt/novu/backup/novu-db-2026-10-21.archive

六、环境变量表

官方 .env.example 全量变量与实测取值(语义与生效服务详见本专栏配置参数详解篇):

变量实测取值说明
JWT_SECRET64 位 hexJWT 签名密钥,必填,openssl rand -hex 32
STORE_ENCRYPTION_KEY32 字符 hex渠道凭证加解密密钥,必填且必须恰好 32 字符
NOVU_SECRET_KEY64 位 hexAPI 侧根密钥来源,必填
SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME15d收件箱组件 JWT 有效期
HOST_NAMEhttp://192.168.146.128对外主机名根
NODE_ENVlocal取值 dev/test/production/ci/local
MONGO_MAX_POOL_SIZE / MIN10 / 5Mongo 连接池上下限
MONGO_INITDB_ROOT_USERNAME / PASSWORDroot / 演示口令Mongo 初始管理员
MONGO_URLmongodb://root:***@mongodb:27017/novu-db?authSource=admin服务连接串(内网服务名)
MONGO_AUTO_CREATE_INDEXEStrue首启自动建索引
REDIS_HOST / REDIS_PORTredis / 6379队列 Redis(内网服务名)
REDIS_PASSWORD空未设密码
REDIS_CACHE_SERVICE_HOST / PORT空 / 6379留空=缓存关闭
REDIS_SKIP_VERSION_CHECKfalse经代理连 Redis 且不支持 INFO 时置 true
S3_LOCAL_STACK${HOST_NAME}:4566S3 兼容端点(官方 compose 未内置该服务,按需自备)
S3_BUCKET_NAME / S3_REGIONnovu-local / us-east-1桶与区域
AWS_ACCESS_KEY_ID / SECRETtest / testS3 访问凭证
API_PORT / WS_PORT / WORKER_PORT3000 / 3002 / 3004容器内端口(勿改,宿主映射在 compose 里改)
REDIS_PORT / REDIS_CACHE_SERVICE_PORT6379 / 6379Redis 端口
VITE_API_HOSTNAME / VITE_WEBSOCKET_HOSTNAME${HOST_NAME}:8148 / :8149前端拼 API/WS 地址
API_ROOT_URL${HOST_NAME}:8148api 对外根地址
FRONT_BASE_URL${HOST_NAME}:8150dashboard 对外根地址
IS_API_IDEMPOTENCY_ENABLEDfalse触发幂等开关
IS_API_RATE_LIMITING_ENABLEDfalseAPI 限流开关
IS_NEW_MESSAGES_API_RESPONSE_ENABLEDtrue新版 messages 响应结构
IS_V2_ENABLEDtruev2 API 体系开关
IS_SELF_HOSTEDtrue自托管标识(必须 true)
IS_EMAIL_INLINE_CSS_DISABLEDfalse邮件内联 CSS 开关
IS_USE_MERGED_DIGEST_ID_ENABLEDfalsedigest 合并 ID 策略
SENTRY_DSN空错误上报(自托管留空)
NEW_RELIC_ENABLED 等false / 占位New Relic 观测,默认关
BROADCAST_QUEUE_CHUNK_SIZE / MULTICAST100 / 100广播/组播批次大小

七、配置参数说明

  • 必改四组:三个密钥(JWT_SECRET/STORE_ENCRYPTION_KEY/NOVU_SECRET_KEY)、HOST_NAME、Mongo 口令、四个对外 URL(VITE_*/API_ROOT_URL/FRONT_BASE_URL)。任何一组与实际环境不符都会以「管理台打不开/登录失败/触发 401」的形式暴露;
  • 改 .env 后必须重建生效:环境变量在容器创建时注入,docker compose up -d 会自动重建配置有变化的服务(实测改 HOST_NAME 后执行一次 up -d,输出里 api/dashboard 等 6 个服务逐个 Recreated);
  • DISABLE_USER_REGISTRATION:官方文档提供的注册开关,加入 .env 并在 api 服务 environment 里透传后,新用户注册被拒(400 Bad Request,Account creation is disabled),已有用户可继续登录;
  • GLOBAL_CONTEXT_PATH 与 API_CONTEXT_PATH/WS_CONTEXT_PATH:反向代理统一前缀场景使用,dashboard 端口不受其控制。

八、配置文件挂载

Novu 各业务服务不使用磁盘配置文件,全部配置经环境变量注入;MongoDB/Redis 亦使用镜像默认配置。因此没有 volumes: 挂载配置文件的环节,需要定制 Redis(如开 AOF)时在 compose 服务上追加 command: ["redis-server","--appendonly","yes"] 与数据卷,需要定制 Mongo 时追加 --keyFile/--replSet 等启动参数。这是 Novu 与传统中间件(Redis/MySQL 单二进制+conf 文件)部署习惯最大的差异。

九、等价 docker run 说明

Novu 是六服务强依赖拓扑(api/worker/ws 依赖 Mongo+Redis 健康检查、dashboard 依赖 api+worker 健康检查),官方发行与运维形态就是 Compose,逐服务转写 docker run 无运维价值。仅给出理解性等价示例(api 一个服务的核心要素):

docker run -d --name api \
  --network novu-3190-stack_default \
  -p 8148:3000 \
  -e NODE_ENV=local \
  -e MONGO_URL='mongodb://root:q1w2e3r4@mongodb:27017/novu-db?authSource=admin' \
  -e REDIS_HOST=redis -e REDIS_PORT=6379 \
  -e JWT_SECRET=fade86f0d43ee13a31d528da5d1acfa41aeabddee5fa49e32b23ed2e54ad0105 \
  -e STORE_ENCRYPTION_KEY=b9c562f194b51df3054236f1a18de9af \
  ghcr.io/novuhq/novu/api:3.19.0

该示例省略了健康检查、依赖顺序、其余十余个环境变量,仅说明单服务可独立运行;实际部署一律回到 compose 形态。

十、常用运维命令

# 服务状态
cd /opt/novu && docker compose ps
# 跟踪日志(-f 全部服务,或 docker compose logs -f api 单服务)
docker compose logs -f --tail 100
# 重启单个服务(改 .env 后的定向生效方式)
docker compose restart api
# 变更 .env 后全量重建(自动 Recreate 受影响服务)
docker compose up -d
# 停止(保留数据卷)
docker compose down
# 彻底销毁(含 MongoDB 数据卷,生产环境禁用)
docker compose down -v

升级操作(以 3.19.0 → 后续新版本为例,官方升级即换镜像 tag):

cd /opt/novu
# 1. 备份 MongoDB(见第五章 mongodump 命令)
# 2. 替换 compose 文件中四个 ghcr.io/novuhq/novu/* 镜像 tag 为目标版本
sed -i 's/novu\/api:3.19.0/novu\/api:3.20.0/; s/novu\/worker:3.19.0/novu\/worker:3.20.0/; s/novu\/ws:3.19.0/novu\/ws:3.20.0/; s/novu\/dashboard:3.19.0/novu\/dashboard:3.20.0/' docker-compose.yml
# 3. 拉取新镜像并滚动重建
docker compose pull && docker compose up -d
# 4. 健康验证(回显应显示新版本号)
curl -sS http://192.168.146.128:8148/v1/health-check

版本与部署核查命令:

docker compose images   # 核对各服务实际运行镜像 tag
api         ghcr.io/novuhq/novu/api         3.19.0   linux/amd64   2.4GB
worker      ghcr.io/novuhq/novu/worker      3.19.0   linux/amd64   2.19GB
ws          ghcr.io/novuhq/novu/ws          3.19.0   linux/amd64   2.12GB
dashboard   ghcr.io/novuhq/novu/dashboard   3.19.0   linux/amd64   402MB

降级与多版本:Novu 无跨版本数据回滚承诺(MongoDB schema 随版本演进),降级 = 恢复备份 + 换回旧 tag 重建。多版本并存时用不同项目目录(各自的 compose name: 不同,如 novu-3190-stack、novu-3200-stack)与不同宿主端口隔离,数据卷随项目名天然隔离。

十一、常见问题(FAQ)

Q1:docker compose up -d 后 api 一直 unhealthy 或反复重启? 查日志 docker compose logs api。实测环境中最常见根因是 .env 的 MONGO_URL 与 Mongo 初始化口令不一致(MONGO_INITDB_ROOT_PASSWORD 改了但 MONGO_URL 里是旧值),api 连库认证失败。把两者改为同一口令后 docker compose down && docker compose up -d 重建即可;若首次启动时就改口令失败过,需 down -v 清卷重来(Mongo 初始用户只在空数据卷时创建)。

Q2:管理台能打开但登录/接口一直报错? 根因是 HOST_NAME/端口变量与实际访问地址不一致(见 4.2.3 ⚠️ 说明)。浏览器 F12 看失败请求的域名端口,把 .env 的 VITE_API_HOSTNAME/VITE_WEBSOCKET_HOSTNAME/API_ROOT_URL/FRONT_BASE_URL 改为浏览器可达的地址,docker compose up -d 重建。

Q3:注册账号报 422 Validation Error? 实测回显:The password must contain minimum 8 and maximum 64 characters, at least one uppercase letter, one lowercase letter, one number and one special character #?!@$%^&*()-。这是 Novu 的密码策略(纯数字 q1w2e3r4 不满足),按策略组合(如 Q1w2e3r4#)即可。

Q4:worker 日志持续出现 Failed to create ClickHouse table? 3.x 引入的 Trace/StepRun 观测数据依赖 ClickHouse,官方 compose 未包含该服务,该报错不影响通知投递主链路(实测触发、feed 查询均正常)。消除噪音可忽略;需要全链路 trace 时自行补 ClickHouse 服务与相关环境变量。

Q5:workflow 保存报 notificationGroupId must be provided 或 message template is missing? 实测结论:这是用错 API 版本的表现——旧的 /v1/workflows 端点按 v0/v1 契约校验;v3.19.0 的 workflow 管理走 /v2/workflows,请求体不再需要 notificationGroupId,步骤 type 用小写枚举(in_app 而非 IN_APP),内容写在 controlValues 里。完整请求体与回显见本专栏 API 使用篇。

Q6:触发事件返回 processed 但收件箱没消息(to 用 topicKey 时)? 实测复现:单发(to.subscriberId)与 bulk 触发正常落地;to: {"topicKey": ...} 的 multicast 触发返回 {"acknowledged":true,"status":"processed"} 后消息不落地(api 日志确认已投递 Workflow 队列,worker 无消费记录,MongoDB notifications/jobs 集合无对应记录)。这是 3.19.0 自托管版的实测行为,生产使用 topic 广播前务必先在自己环境验证;排查路径:api 日志搜 dispatched to [Workflow] Queue → worker 日志按 transactionId 搜 → mongosh 查 novu-db 的 notifications/jobs 集合。

Q7:内存不足时哪些服务先出问题? worker 与 api 是 Node 大内存服务(镜像 2.4GB 级),4GB 以下内存机器上常表现为 workflow job 长时间 pending、api 健康检查超时。按官方基线给足内存,或仅保留核心通知量最小的部署形态(官方不建议裁剪服务)。

十二、参考链接