生产部署
三步
章节:三步cp .env.example .env # 填真实值,绝不提交vi deploy/Caddyfile # 把 example.com 换成你自己的域名make up # = docker compose -f deploy/compose.yml up -d --build拓扑
章节:拓扑deploy/compose.yml 起五个服务:
| 服务 | 职责 |
|---|---|
| caddy | 自动 HTTPS,对外唯一入口 |
| web | Next.js 应用,:4800 |
| jobs | 定时任务 worker |
| postgres | 数据库 |
| wal-g | 每日基础备份 + 持续 WAL 归档(可 PITR) |
Caddy 需要一个真实的公网域名指向这台机器才能签证书。对外只开 22 / 80 / 443。
上线前必须改的三项
章节:上线前必须改的三项| 项 | 说明 |
|---|---|
APP_ENCRYPTION_KEY | 32 字节 base64,加密 auth_connections。.env.example 里是公开的占位符,必须换成真实随机值 |
SESSION_SECRET | cookie 签名。同上,必须换成真实随机值 |
E2E_TEST_MODE | 必须为 0。置 1 会打开演示模式(mock 登录提供方、可拨动时钟、开放 /api/__test/*) |
生成随机值:
openssl rand -base64 32 # APP_ENCRYPTION_KEYopenssl rand -base64 48 # SESSION_SECRET完整变量清单见环境变量参考。
起来之后
章节:起来之后首次起来同样要跑一次迁移 + 种子(或自建机构),否则会撞上首次初始化必读里那条「不跑种子 = 仅底座」。
用已经构建好的镜像
章节:用已经构建好的镜像镜像在别处(CI / 镜像服务)构建好,服务器只负责拉起来,不装 Node / pnpm、不在线上机器编译:
export OPSKOOL_IMAGE=<registry>/<repo>:<tag>docker compose -f deploy/compose.yml -f deploy/compose.image.yml up -dcompose.image.yml 顺带补了一个一次性 migrate 服务,web/jobs 等它跑完才起——第一次部署时库里连 opskool_app / opskool_auth 两个角色都还不存在(由迁移创建)。迁移是幂等的,每次 up 都跑,跑过的是空操作。
种子不含在里面(seed 跑第二次会再建一个机构)。首次部署后手工跑一次:
docker compose -f deploy/compose.yml -f deploy/compose.image.yml \ run --rm migrate pnpm --filter @opskool/db run seed公开演示站:每天自动还原
章节:公开演示站:每天自动还原演示站每天定时 TRUNCATE 全部表 + 重跑种子,把库还原成最初形态;任何人留下的数据当天过后一律消失。
有两条路线,二选一,不要混着叠。
路线 A:一份自包含文件(推荐)
章节:路线 A:一份自包含文件(推荐)deploy/compose.public-demo.yml 一条命令跑完。把它和一份填好的 .env 复制到服务器上同一个目录,compose 文件改名 compose.yml,然后:
docker pull <registry>/<repo>:<tag> # 这步不能省,见下docker compose up -d
# 首次部署后手工种一次(migrate 只跑迁移,不含种子)docker compose run --rm migrate pnpm --filter @opskool/db run seed这条路线的 OPSKOOL_IMAGE 可以直接写进同目录那份 .env——compose 的 ${...}
认的就是 compose 文件自己目录下的 .env。(这正是它和路线 B 的差别之一:文件在 deploy/ 子目录时,${...} 找的是 deploy/.env 而不是仓库根的 .env。)
路线 B:三层 override
章节:路线 B:三层 override适合已经在用 compose.yml 全套(含 Caddy 自动 HTTPS 与 wal-g 备份)、只想加一个每日还原的场合:
export OPSKOOL_IMAGE=<registry>/<repo>:<tag>docker compose -f deploy/compose.yml -f deploy/compose.image.yml \ -f deploy/compose.demo-site.yml up -d两条路线共同的要点
章节:两条路线共同的要点- 还原时间由
DEMO_RESET_UTC_HOUR决定,UTC 24 小时制,默认20= 北京时间次日 04:00 (alpine 底座没装 tzdata,写时区名不会生效)。 .env里的SEED_DEMO_PASSWORD必须设成固定值——留空的话每天还原都会重新随机生成、只在容器日志里打印一次,第二天没人知道演示账号的密码是什么。这是首次初始化必读那条「公网实例别设固定密码」的唯一例外。
门口的反向代理:必须透传 Host
章节:门口的反向代理:必须透传 Host只要 web 前面有你自己的反向代理(Nginx、网关、云负载均衡),它必须把客户端原始的
Host 原样透传:
proxy_set_header Host $http_host;proxy_set_header X-Forwarded-Host $http_host;本页是 CE README「Docker 部署」一节的展开;两处不一致时,以 README 为准。
© 2026 OpSkool 办学帮 · 苏ICP备2025224982号-3