部署

使用 Vercel 或 Docker 将 Next.js 模板部署到生产环境。

模板以 Next.js standalone 输出模式构建,并附带一个多阶段 Dockerfile。本页介绍 质量门禁、两种部署目标,以及一份上线前检查清单。

质量门禁

每次部署前运行:

pnpm lint
pnpm build

pnpm build 会生成 Docker 所使用的 standalone 服务器。

构建时 vs. 运行时配置

NEXT_PUBLIC_* 变量在构建时被内联,运行中的容器无法更改 —— 它们必须在 pnpm build 运行时就已存在,更改它们需要重新构建。服务端密钥(DATABASE_URLBETTER_AUTH_SECRETCREEM_API_KEYRESEND_API_KEY 等)在运行时读取。请据此 规划流水线,使公开 ID(如 NEXT_PUBLIC_CREEM_PRODUCT_*)在构建时而非仅在运行时 设置。

Vercel

  1. 在 Vercel 中导入仓库。
  2. 添加环境变量 —— 构建时的 NEXT_PUBLIC_* 与运行时密钥都要加。
  3. 准备带连接池的托管 PostgreSQL 并设置 DATABASE_URL
  4. BETTER_AUTH_URL 设为生产域名并注册 OAuth 回调。

Vercel 的文件系统是临时的。本地图片上传写入 public/uploads,在 Vercel 上不会 持久化。在部署依赖上传的功能前,请将上传迁移到对象存储 —— 见 存储

Docker / 自托管

next.config.mjs 设置了 output: "standalone",而 Dockerfile 是多阶段构建:

  • 基础镜像 node:22-alpine,通过 Corepack 启用 pnpm。
  • deps--frozen-lockfile 安装;builder 运行 pnpm build
  • runner 以非 root 用户(nextjs,uid 1001)运行,并复制 public.next/standalone.next/static
  • 暴露端口 3000,设置 HOSTNAME=0.0.0.0,并以 node server.js 启动。
docker build -t soar-next .
docker run -p 3000:3000 --env-file .env soar-next

通过 --env-file/编排器密钥提供运行时密钥,并确保构建时的 NEXT_PUBLIC_* 值在 docker build 期间可用。

上线前检查清单

  • 数据库 —— 带连接池的托管 PostgreSQL;真正的迁移工作流(而非仅 drizzle-kit push —— 见 数据库)。
  • Better Auth —— 生产 BETTER_AUTH_URL 与全新、保密的 BETTER_AUTH_SECRET
  • OAuth —— 为 GitHub/Google 注册生产回调 URL。
  • Creem —— 正式服务器索引、正式产品 ID,以及在 Creem 中注册带 CREEM_WEBHOOK_SECRET 的 webhook(/api/payment/notify/creem)。
  • Resend —— 已验证的发信域名;正确的 fromEmail/supportEmail
  • 站点/元数据 —— 将 NEXT_PUBLIC_SITE_URL 设为你的域名,并更新 src/app/[locale]/layout.tsx 中的标题/描述元数据(见 站点配置)。
  • AI 密钥 —— 若启用相关功能,配置 OPENAI_API_KEY / REPLICATE_API_TOKEN
  • 存储 —— 启用上传前配置好持久的对象存储。

AI 聊天与媒体路由是公开示例,没有认证、限流、校验或配额。在生产环境暴露它们前 请先加上这些控制 —— 见 AI 聊天AI 媒体

收尾确认

  • 若你向用户收费,确认 webhook 生命周期覆盖(取消/退款/过期)。
  • 配置数据库备份、日志聚合、分析与错误上报。
  • 规划密钥轮换。

冒烟测试

部署后,端到端验证每个界面:

  • 认证:注册、验证邮箱、登录、OAuth、重置密码、登出。
  • 邮件:验证与联系消息能送达。
  • 支付:结账创建订单;webhook 将其标记为 success
  • 仪表盘:登出时受保护路由会重定向。
  • 内容:文档、博客与法律页面正常渲染。
  • 语言:/(英文)与 /zh 路由都可用。
  • AI:聊天与媒体生成有响应(若启用)。
  • 上传:图片上传对接持久存储后正常(若启用)。

相关页面

On this page