Rallly 4.16 Docker Compose 部署指南
从零部署 Rallly 4.16 的两条官方路径对比与手动 Compose 全流程实测:必需环境变量、OTP 登录验证、SMTP/S3/外部反代可选组件,附 5 段真实排障实录(zod 校验、密码长度、PG 初始化、跨网络隔离、旧变量废弃)。
Rallly 4.16 Docker Compose 部署指南
适用版本:Rallly v4.16.2(2026-10-23 发布)。本文所有命令与回显均在真实服务器口径下实测(查询日期 2026-10-24),数据库迁移数量、报错文本均为逐行实录。
一、部署前决策:官方两条路径怎么选
Rallly 官方自托管文档(support.rallly.co/self-hosting)目前只维护一种"推荐形态":Rallly CLI 安装器。两条路径对比如下:
| 路径 | 形态 | 适合谁 |
|---|---|---|
| A. 官方安装器(推荐) | `curl -fsSL https://get.rallly.co | bash把整套栈安装到/opt/rallly,包含 App + PostgreSQL + Garage(S3) + Traefik(反代),并用统一的 rallly.sh` 脚本管理 |
| B. 手动 Compose(本篇主线) | 官方预构建应用(lukevella/rallly:4.16.2)+ 自备 PostgreSQL,自行编写 Compose 文件 | 已有自己的 PostgreSQL/反代/证书体系,或需要把 App 编入既有部署体系 |
安装器路径的默认形态会申请 Let's Encrypt 证书并独占 80/443,还需要提前把域名 A 记录指向服务器。如果你的服务器已有 nginx/caddy 在跑,安装器支持 PROXY_MODE=external 切换为外部反代模式(详见第六节),但既有的证书与路由就需要自己接管。
两条路径的底层组件完全一致,本文主线走路径 B——它最透明,也最能讲清楚 Rallly 的依赖链;rallly.sh 管理命令在《Rallly 4.16 常用 CLI 命令详解》中单篇实测。
二、系统要求(官方自托管文档口径)
- 服务器内存 ≥ 2 GB(Rallly + PostgreSQL 合计的最小实用配置)。
- Docker 19.03+ 与 Docker Compose v2。
- 一个可用域名,或至少一个可访问的服务器地址(应用启动强制要求
NEXT_PUBLIC_BASE_URL指向真实可访问 URL)。 - SMTP 投递能力:登录验证码、邀请、通知邮件都依赖邮件发送;没有 SMTP 就无法登录(验证码发不出去)。内网环境可搭 Mailpit/MailHog 做接收调试。
- PostgreSQL:必需依赖,推荐 18(官方栈默认
POSTGRES_VERSION=18)。
三、准备目录与 Compose 文件
先在工作目录放置 Compose 文件与数据库目录(示例统一放在 /opt/rallly-stack,实际位置随意):
mkdir -p /opt/rallly-stack/pgdata
cd /opt/rallly-stack
Compose 文件(docker-compose.yml),仅包含必需的两个服务:
name: rallly-4.16.2-stack
services:
rallly_db:
image: postgres:18-alpine
container_name: rallly-4.16.2-db
restart: unless-stopped
volumes:
- ./pgdata:/var/lib/postgresql
environment:
- POSTGRES_PASSWORD=ralllydb
- POSTGRES_DB=rallly
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 10
rallly_web:
image: lukevella/rallly:4.16.2
container_name: rallly-4.16.2-web
restart: unless-stopped
depends_on:
rallly_db:
condition: service_healthy
ports:
- "8133:3000"
environment:
- DATABASE_URL=postgres://postgres:ralllydb@rallly_db/rallly
- SECRET_PASSWORD=q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4
- SUPPORT_EMAIL=admin@example.com
- NEXT_PUBLIC_BASE_URL=http://127.0.0.1:8133
四个应用环境变量一个都不能少(作用见《Rallly 4.16 配置参数详解》):
DATABASE_URL:PostgreSQL 连接串,服务名rallly_db由 Compose 内部 DNS 解析。SECRET_PASSWORD:会话加密密钥,最少 32 个字符(源码 zod 校验z.string().min(32),实测第五节有翻车实录)。SUPPORT_EMAIL:站点支持邮箱,校验类型为邮箱格式。NEXT_PUBLIC_BASE_URL:站点对外访问地址(4.16 起的变量名;旧版本的NEXT_PUBLIC_URL已废弃,实测传入会被静默忽略)。
四、首次启动实录
$ docker compose up -d
[+] Running 3/3
✔ Network rallly-4162-stack_default Created
✔ Container rallly-4.16.2-db Healthy
✔ Container rallly-4.16.2-web Started
首次启动会自动执行 Prisma 数据库迁移,日志实录(docker logs -f rallly-4.16.2-web,首尾节选):
No .env file found, continuing without it
Loaded Prisma config from prisma.config.ts.
Prisma schema loaded from prisma.
Datasource "db": PostgreSQL database "rallly", schema "public" at "rallly_db"
166 migrations found in prisma/migrations
Applying migration `20220315143815_init`
...(中略,共 166 条,最新一条为 20261019120000_poll_activities_user_id_index)
Applying migration `20261019120000_poll_activities_user_id_index`
探活首页:
$ curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:8133/
HTTP 200
运行时版本可在日志中确认(实测输出):
▲ Next.js 16.4.2
五、登录验证:OTP 全链路实测
Rallly 4.16 的账号体系是"邮箱验证码登录"(Better Auth 的 emailOTP),注册与登录是同一个入口 /login:
- 在登录页输入邮箱提交,系统调用
POST /api/better-auth/email-otp/send-verification-otp(实测返回{"success":true})。 - 邮箱收到 6 位验证码,邮件正文实录(调试环境用 Mailpit 接收):
VERIFY YOUR EMAIL ADDRESS
Please use the following 6-digit verification code to verify your email
925718
This code is valid for 15 minutes
- 提交验证码后登录成功,服务端返回会话(实测响应节选):
{"token":"QPvUKKP1sg7qZpBRjQYKtVCXtGdgNxSp","user":{"email":"admin@example.com","emailVerified":true,"role":"user",...}}
浏览器会写入 better-auth.session_token Cookie(HttpOnly,默认 60 天有效期)。首个用户落库后,如果部署时配置了 INITIAL_ADMIN_EMAIL 且与该邮箱一致,访问 /admin-setup(实测 HTTP 200)即可认领管理控制面板管理员身份。
六、可选组件与生产化调整
6.1 SMTP(生产必配)
内网调试可用 Mailpit(SMTP 端口 1025、Web 界面 8025)接收验证码;生产环境换真实邮件服务,把以下变量加入 rallly_web 的 environment(完整参数见配置篇):
- SMTP_HOST=smtp.example.com
- SMTP_PORT=587
- SMTP_SECURE=false
- SMTP_USER=mailer@example.com
- SMTP_PWD=你的SMTP密码
6.2 对象存储(可选)
头像上传等需要 S3 兼容存储;不配置 S3 时应用功能正常(实测部署未配 S3 也能完整走通登录),只是上传能力受限:
- S3_ENDPOINT=http://minio.example.com:9000
- S3_BUCKET_NAME=rallly
- S3_ACCESS_KEY_ID=xxxx
- S3_SECRET_ACCESS_KEY=xxxx
- S3_REGION=us-east-1
6.3 外部反代模式
生产建议前置 nginx/caddy/traefik 做证书与域名,应用仅监听本机回环:
ports:
- "127.0.0.1:3000:3000"
反代侧需要把 NEXT_PUBLIC_BASE_URL 对应的域名(如 https://rallly.example.com)转发到 127.0.0.1:3000,并放行 WebSocket(投票页实时刷新需要)。官方安装器形态即内建 Traefik 完成这件事;手动路径 PROXY_MODE 变量是官方栈脚本层的开关,纯手动 Compose 无需设置。
七、排障实录(本篇部署路径真实踩坑)
7.1 缺必需环境变量:zod 校验直接拒绝启动
故意只给 DATABASE_URL 启动,日志实录:
❌ Invalid environment variables: [
{
expected: 'string',
code: 'invalid_type',
path: [ 'SECRET_PASSWORD' ],
message: 'Invalid input'
},
{
expected: 'string',
code: 'invalid_type',
path: [ 'SUPPORT_EMAIL' ],
message: 'Invalid input'
},
{
expected: 'string',
code: 'invalid_type',
path: [ 'NEXT_PUBLIC_BASE_URL' ],
message: 'Invalid input'
}
]
Failed to prepare server Error: An error occurred while loading instrumentation hook: Invalid environment variables
处置:把四个必需变量补齐即可,报错清单会精确列出缺失项。
7.2 SECRET_PASSWORD 少于 32 字符
设为 q1w2e3r4(8 字符)启动,日志实录:
❌ Invalid environment variables: [
{
origin: 'string',
code: 'too_small',
minimum: 32,
inclusive: true,
path: [ 'SECRET_PASSWORD' ],
message: 'Invalid input'
}
]
其余变量全部通过,仅这一条报错——源码校验 z.string().min(32) 与实测一致,请直接给 32 位以上随机串。
7.3 PostgreSQL 密码未设置导致数据库重启循环
官方安装器会为 PostgreSQL 自动生成密码,但手动部署若只给了 POSTGRES_DB 没给 POSTGRES_PASSWORD,数据库进入重启循环,日志实录:
Error: Database is uninitialized and superuser password is not specified.
You must specify POSTGRES_PASSWORD to a non-empty value for the
superuser.
处置:在数据库服务加 POSTGRES_PASSWORD=<强密码> 并同步更新 DATABASE_URL。注意若数据目录已经以"失败状态"初始化,需清空 pgdata 后重建(首次部署无数据时直接删目录即可)。
7.4 跨网络访问隔离(Compose 默认网络)
把 SMTP 调试工具(Mailpit)部署在另一个 Compose 网络时,Rallly 发信会静默失败(验证码邮件收不到,应用日志无显性报错)。实测从应用侧探测:
http=000
原因:Docker 不同 bridge 网络之间默认隔离。处置:用外部网络把两个栈挂在同一网络下,或把 Mailpit 编入同一 Compose 文件。
7.5 旧版环境变量 NEXT_PUBLIC_URL 被静默忽略
给 4.16.2 传入旧变量 NEXT_PUBLIC_URL=http://legacy.example.com,服务正常启动(HTTP 200),无任何警告——该变量已从源码 env 定义中移除,真实生效的只有 NEXT_PUBLIC_BASE_URL。从旧版本升级时必须改名,否则站点仍按旧地址生成链接。
八、升级要点
- 备份先行:
pg_dump导出(CLI 路径可直接用rallly.sh backup,实测产物rallly_20261024_112602.sql.gz)。 - 固定版本号升级:把
lukevella/rallly:4.16.2改为新 tag(如跟随4跟踪 tag 则docker compose pull拉取),docker compose up -d重建;启动时自动跑增量迁移(实测 4.16.2 首启为 166 个迁移,升级时只补新增部分)。 - 大版本升级前阅读官方 release notes:4.x 系列内环境变量存在改名与废弃(如
NEXT_PUBLIC_URL→NEXT_PUBLIC_BASE_URL、SMTP_TLS_ENABLED→SMTP_REJECT_UNAUTHORIZED),逐项核对配置篇的参数表。
九、相关文档
- 产品选型与许可解读:《Rallly 4.16 介绍与选型指南》
- 全量环境变量字典:《Rallly 4.16 配置参数详解》
- 日常运维(启停/日志/备份):《Rallly 4.16 常用 CLI 命令详解》