上线与维护

部署指南

01MVP Starter Kit 生产部署全流程指南

01MVP Starter Kit 是一个 pnpm workspace + Turborepo monorepo。

当前首选生产路径是 Vercel。Dockerfile 和 Cloudflare Workers 路径保留,但不要把它们当成默认部署方式。


部署前检查清单

在触发任何部署之前,逐项确认以下内容:

  • 本地 pnpm build 构建成功,无 TypeScript 错误
  • pnpm db:status 确认所有 migration 已提交到 Git
  • .env.local 中所有必填变量已同步到生产环境
  • BETTER_AUTH_URLNEXT_PUBLIC_SITE_URL 指向生产域名(非 localhost)
  • OAuth 回调 URL 已在第三方平台更新为生产域名
  • 数据库连接串可从部署平台网络访问
  • S3 存储桶权限已配置(公开读、私有写)
  • AI API Key 余额充足
  • 支付 Webhook 地址已配置为生产域名
  • 邮件服务 API Key 已配置

Vercel 部署

Vercel 是 01MVP 的首选部署平台。以下是从零到上线的完整流程。

第一步:导入项目

连接 Git 仓库

登录 Vercel Dashboard,点击 "Add New Project",选择你的 GitHub/GitLab 仓库并授权。

配置 Root Directory

有两种方式,任选其一:

方式 A:设置 Root Directory(推荐)

在 Vercel 项目设置中,将 Root Directory 设为:

apps/01mvp-web

这样 Vercel 会自动识别 Next.js 项目,构建命令默认为 pnpm build,输出目录为 .next

方式 B:保持仓库根目录

如果 Root Directory 保持为仓库根目录,需要手动设置构建命令:

pnpm --filter 01mvp-web build

输出目录设为 apps/01mvp-web/.next

推荐方式 A。设置 Root Directory 后,Vercel 的 Next.js 检测、自动优化、Preview Deployment 都能正常工作,无需额外配置。

选择 Framework Preset

如果使用方式 A,Vercel 会自动检测为 Next.js。如果未自动识别,手动选择 "Next.js"。

Node.js 版本确认为 22.x(项目要求 >=22)。

配置环境变量

点击 "Environment Variables" 展开,逐个添加变量。详见下方环境变量完整清单。

环境变量遗漏是部署失败最常见的原因。不要跳过这一步。具体必填项以配置说明为准。

点击 Deploy

确认配置后点击 Deploy。等待构建完成,检查构建日志确认:

  • Prisma Client 已生成
  • Next.js 构建通过
  • 运行时能读取到 DATABASE_URL 和鉴权变量

Vercel 环境变量

在 Vercel Dashboard 中进入项目 Settings > Environment Variables 页面配置。

每个变量可以针对不同环境设置不同值:

环境说明
Production推送到生产分支(默认 main)时使用
PreviewPR Preview 和非生产分支部署时使用
Development本地 vercel dev 时使用(通常用 .env.local 代替)

环境变量完整清单

核心变量(必填)

变量名说明Production 示例Preview 示例
DATABASE_URLPostgreSQL 连接串postgresql://user:pass@host:5432/prodpostgresql://user:pass@host:5432/dev
BETTER_AUTH_SECRETAuth 签名密钥随机生成的强密钥同上或独立密钥
BETTER_AUTH_URLAuth 回调基础 URLhttps://01mvp.comhttps://preview.01mvp.com
NEXT_PUBLIC_SITE_URL站点公开 URLhttps://01mvp.comhttps://preview.01mvp.com

S3 存储(必填)

变量名说明
S3_ENDPOINTS3 API 端点(如腾讯云 COS)
S3_REGION存储桶区域
S3_ACCESS_KEY_ID访问密钥 ID
S3_SECRET_ACCESS_KEY访问密钥 Secret
S3_BUCKET存储桶名称
NEXT_PUBLIC_BUCKET_NAME公开读取的桶名称
NEXT_PUBLIC_S3_ENDPOINT公开访问端点 URL

AI 服务(必填)

变量名说明默认值
OPENAI_API_KEYAI API 密钥-
OPENAI_BASE_URLAPI 基础 URLhttps://api.deepseek.com
OPENAI_MODEL模型名称deepseek-v4-flash

OAuth 登录(按需)

变量名说明
GOOGLE_CLIENT_IDGoogle OAuth Client ID
GOOGLE_CLIENT_SECRETGoogle OAuth Client Secret
GITHUB_CLIENT_IDGitHub OAuth Client ID
GITHUB_CLIENT_SECRETGitHub OAuth Client Secret
WECHAT_WEBSITE_APP_ID微信网站应用 AppID
WECHAT_WEBSITE_APP_SECRET微信网站应用 AppSecret

支付(按需)

变量名说明
STRIPE_SECRET_KEYStripe Secret Key
STRIPE_WEBHOOK_SECRETStripe Webhook 签名密钥
NEXT_PUBLIC_STRIPE_PRICE_PRO_MONTHLY月付价格 ID
NEXT_PUBLIC_STRIPE_PRICE_PRO_YEARLY年付价格 ID
WAFFO_MERCHANT_IDWaffo 商户 ID
WAFFO_PRIVATE_KEYWaffo 私钥

邮件(按需)

变量名说明
PLUNK_API_KEYPlunk/Zeabur 邮件 API Key
EMAIL_FROM发件人地址
CONTACT_EMAIL联系邮箱

可选变量

变量名说明
NEXT_PUBLIC_UMAMI_WEBSITE_IDUmami 统计 ID
NEXT_PUBLIC_UMAMI_SCRIPT_URLUmami 脚本地址
NEXT_PUBLIC_GOOGLE_ANALYTICS_IDGoogle Analytics ID
TRUSTED_ORIGINSCORS 信任源(逗号分隔)

Production vs Preview 环境差异

维度ProductionPreview
数据库生产数据库(独立实例)测试数据库或开发库
域名自定义域名*.vercel.app
Auth URL生产域名Preview 域名
OAuth 回调生产回调地址需在第三方平台注册 Preview 域名
支付 Webhook生产 Webhook测试/沙箱 Webhook
环境变量使用 Vercel "Production" 作用域使用 "Preview" 作用域

Preview 部署会使用 Preview 作用域的环境变量。如果 Preview 环境变量未单独设置,Vercel 不会回退到 Production 变量——它会使用空值。确保 Preview 环境也配置了 DATABASE_URL 等核心变量。

自定义域名

在 Vercel 添加域名

进入项目 Settings > Domains,输入你的域名(如 01mvp.com),点击 Add。

配置 DNS 记录

根据 Vercel 提示,在 DNS 提供商处添加记录:

方式 A:CNAME(推荐用于子域名)

类型: CNAME
名称: www(或其他子域名)
值: cname.vercel-dns.com

方式 B:A 记录(用于根域名)

类型: A
名称: @(根域名)
值: 76.76.21.21

方式 C:Nameserver(完整托管)

将域名的 Nameserver 切换为 Vercel 提供的 NS 记录,Vercel 会自动管理所有 DNS。

等待生效

DNS 记录生效通常需要几分钟到几小时。Vercel 会自动签发 SSL 证书。

验证方式:访问域名,确认 HTTPS 正常、页面加载无错。

更新环境变量

域名确认后,更新 Vercel 环境变量:

BETTER_AUTH_URL=https://你的域名.com
NEXT_PUBLIC_SITE_URL=https://你的域名.com

重新触发部署使变量生效。

如果同时使用 Cloudflare 代理(橙色云朵),确保 SSL/TLS 模式设为 "Full" 或 "Full (Strict)",否则会出现重定向循环。


Docker 部署

Zeabur 支持 Dockerfile 部署,适合需要自管运行时镜像的场景。

连接仓库

在 Zeabur 控制台创建服务,连接你的 Git 仓库。

配置构建

在服务设置中:

  • 工作目录设为仓库根目录
  • 启用 Dockerfile 部署模式
  • 设置环境变量:
ZBPACK_APP_DIR=apps/01mvp-web
ZBPACK_DOCKERFILE_NAME=01mvp-web

Zeabur 会使用 Dockerfile.01mvp-web 进行构建。

配置环境变量

在 Zeabur 服务的 "Variables" 页面,添加所有必需的环境变量。变量名与 Vercel 环境变量清单一致。

Zeabur 提供的内置变量(如 PORT)会自动注入,无需手动配置。

绑定域名

在 Zeabur 服务的 "Networking" 页面绑定自定义域名,并在 DNS 侧配置 CNAME 指向 Zeabur 提供的地址。

部署并验证

触发部署,等待构建完成。检查服务日志确认启动正常。

适用于自有 VPS 或 K8s 集群。

构建镜像

在仓库根目录执行:

docker build -f Dockerfile.01mvp-web -t 01mvp-web:latest \
  --build-arg DATABASE_URL="postgresql://..." \
  --build-arg BETTER_AUTH_SECRET="your-secret" \
  --build-arg BETTER_AUTH_URL="https://your-domain.com" \
  --build-arg NEXT_PUBLIC_SITE_URL="https://your-domain.com" \
  --build-arg S3_ENDPOINT="https://cos.ap-guangzhou.myqcloud.com" \
  --build-arg S3_REGION="ap-guangzhou" \
  --build-arg S3_ACCESS_KEY_ID="your-key" \
  --build-arg S3_SECRET_ACCESS_KEY="your-secret" \
  --build-arg S3_BUCKET="your-bucket" \
  --build-arg NEXT_PUBLIC_S3_ENDPOINT="https://your-bucket.cos.ap-guangzhou.myqcloud.com" \
  --build-arg OPENAI_API_KEY="your-key" \
  --build-arg OPENAI_BASE_URL="https://api.deepseek.com" \
  --build-arg OPENAI_MODEL="deepseek-v4-flash" \
  .

--build-arg 会在构建缓存中留下痕迹。生产环境建议使用 docker buildx build --secret 或在运行时通过环境变量注入敏感值。

运行容器

docker run -d \
  --name 01mvp-web \
  -p 7001:7001 \
  -e DATABASE_URL="postgresql://..." \
  -e BETTER_AUTH_SECRET="your-secret" \
  -e BETTER_AUTH_URL="https://your-domain.com" \
  -e NEXT_PUBLIC_SITE_URL="https://your-domain.com" \
  01mvp-web:latest

容器暴露端口 7001,使用 Next.js standalone 输出模式运行。

Dockerfile 构建流程

每个 Dockerfile 遵循同一套路:

在仓库根目录执行 turbo prune --docker,裁剪出单 app + 必要依赖

只安装裁剪后 workspace 的依赖

构建 Next.js standalone 输出(使用 --max-old-space-size=8192 防止 OOM)

使用 node:22-slim 运行时镜像以非 root 用户启动服务

docker-compose 参考

version: '3.8'
services:
  01mvp-web:
    build:
      context: .
      dockerfile: Dockerfile.01mvp-web
    ports:
      - "7001:7001"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mvp
      - BETTER_AUTH_SECRET=your-secret
      - BETTER_AUTH_URL=https://your-domain.com
      - NEXT_PUBLIC_SITE_URL=https://your-domain.com
    restart: unless-stopped
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mvp
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Cloudflare

目前可以用 Cloudflare 管理 DNS/CDN。直接部署到 Cloudflare Workers 需要走 @opennextjs/cloudflare 路径,并单独验证数据库、文档资产和运行时兼容性,暂不作为默认生产路径。


环境变量管理

多环境策略

01MVP 项目使用以下环境文件管理本地开发变量:

文件用途是否提交到 Git
.env.example变量模板,列出所有变量名和说明
.env.local本地开发变量(含真实密钥)否(已在 .gitignore)
.env.prd本地模拟生产环境时使用

最佳实践

  1. 敏感变量只在部署平台设置DATABASE_URLBETTER_AUTH_SECRET、API Key 等永远不要出现在代码或 Git 中
  2. 公开变量用 NEXT_PUBLIC_ 前缀:这些变量会被打包到客户端 bundle,不包含敏感信息
  3. 生产环境使用独立数据库:不要让生产环境和开发环境共用同一个数据库
  4. 定期轮换密钥BETTER_AUTH_SECRET 泄露后需要重新生成并重新部署
  5. Preview 环境隔离:Preview 部署应使用独立的测试数据库,避免污染生产数据

同步变量到 Vercel

可以使用 Vercel CLI 批量导入环境变量:

# 安装 Vercel CLI
npm i -g vercel

# 从 .env 文件导入到 Production 环境
vercel env pull .env.vercel.production --environment=production

# 手动添加单个变量
vercel env add DATABASE_URL production

也可以在 Vercel Dashboard 中直接从 .env 文件粘贴批量添加。


数据库迁移策略

迁移原则

数据库变更必须使用迁移,绝对不要直接在生产库上做临时变更。

迁移工作流

开发阶段:创建迁移

修改 apps/01mvp-web/prisma/schema.prisma 后,创建迁移文件:

pnpm db:migrate

这会在本地开发数据库上执行迁移并生成 SQL 文件。

提交迁移文件

将生成的 migration 文件夹(prisma/migrations/)提交到 Git。

漏提交 migration 文件是上线失败的高频原因。提交前检查 git status 确认 migration 文件已暂存。

部署前:在目标数据库执行迁移

在生产部署之前,单独执行迁移并确认结果:

pnpm db:deploy

db:deploy 不会创建新的迁移,只执行已提交但未应用的迁移。

验证迁移结果

# 检查迁移状态
pnpm db:status

# 或使用 Prisma Studio 直接查看表结构
pnpm db:studio

触发应用部署

确认迁移成功后,推送代码触发 Vercel 部署。

迁移注意事项

  • 永远先迁移,后部署应用。新代码可能依赖新表结构,反过来部署会直接报错
  • 迁移脚本应该是幂等的。虽然 Prisma Migrate 会跟踪已应用的迁移,但确保迁移 SQL 本身可重复执行
  • 大表迁移需要评估影响。ALTER TABLE 在大表上可能锁表,生产环境建议在低峰期执行
  • 回滚方案:Prisma Migrate 没有内置回滚。重要迁移前先备份数据库,或手动编写回滚 SQL

接入已有数据库

如果数据库已有表结构,第一次纳入 Prisma Migrate 管理时:

# 1. 确认当前数据库状态
pnpm db:status

# 2. 创建初始迁移(不执行)
pnpm db:migrate --create-only --name init

# 3. 标记为已应用(不实际执行 SQL)
pnpm db:migrate --name init --skip-generate

或使用:

prisma migrate resolve --applied <migration_name>

部署后验证

部署完成后,逐项验证以下功能:

基础访问

  • 网站可通过域名正常访问
  • HTTPS 证书有效,无浏览器安全警告
  • 页面加载速度正常(无超时或 500 错误)
  • 无控制台错误(打开浏览器 DevTools 检查)

用户认证

  • 注册新账号流程正常
  • 登录/登出正常
  • OAuth 登录(Google/GitHub/微信)回调正常
  • Session 持久化正常(刷新页面后仍为登录状态)

数据库

  • 数据读写正常
  • 新注册用户数据写入成功
  • Prisma Client 连接正常(无连接池错误)

文件上传

  • 图片/文件上传到 S3 正常
  • 上传后可正常访问和展示
  • S3 签名 URL 未过期

AI 功能

  • AI 对话功能正常响应
  • API Key 有效、余额充足

支付(如已配置)

  • Stripe/Waffo 支付页面可正常加载
  • Webhook 回调地址指向生产域名
  • 测试支付流程完整

邮件(如已配置)

  • 注册/登录邮件正常发送
  • 邮件发件人地址正确
  • 邮件内容中的链接指向生产域名

常见部署问题


部署检查清单

以下是完整的部署检查清单:

Vercel 配置

  • Root Directory 设为 apps/01mvp-web 或构建命令为 pnpm --filter 01mvp-web build
  • Node.js 版本为 22.x
  • Framework Preset 为 Next.js

环境变量

  • DATABASE_URL 指向生产数据库
  • BETTER_AUTH_SECRET 已设置(非默认值)
  • BETTER_AUTH_URL 指向生产域名
  • NEXT_PUBLIC_SITE_URL 指向生产域名
  • S3 相关变量全部配置
  • AI 相关变量全部配置
  • 支付 Webhook 地址更新为生产域名
  • OAuth 回调地址更新为生产域名

数据库

  • migration 文件已提交到 Git
  • pnpm db:deploy 已在生产数据库执行
  • pnpm db:status 确认所有迁移已应用

域名

  • 自定义域名已在 Vercel 添加
  • DNS 记录已配置
  • HTTPS 证书自动签发成功
  • 域名和 NEXT_PUBLIC_SITE_URL 保持一致

验证

  • 构建日志确认 Prisma Client 和 Next.js build 都已通过
  • 部署后访问首页正常
  • 登录注册流程正常
  • 核心功能验证通过(参考"部署后验证"章节)