部署指南
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_URL和NEXT_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)。
点击 Deploy
确认配置后点击 Deploy。等待构建完成,检查构建日志确认:
- Prisma Client 已生成
- Next.js 构建通过
- 运行时能读取到
DATABASE_URL和鉴权变量
Vercel 环境变量
在 Vercel Dashboard 中进入项目 Settings > Environment Variables 页面配置。
每个变量可以针对不同环境设置不同值:
| 环境 | 说明 |
|---|---|
| Production | 推送到生产分支(默认 main)时使用 |
| Preview | PR Preview 和非生产分支部署时使用 |
| Development | 本地 vercel dev 时使用(通常用 .env.local 代替) |
环境变量完整清单
核心变量(必填)
| 变量名 | 说明 | Production 示例 | Preview 示例 |
|---|---|---|---|
DATABASE_URL | PostgreSQL 连接串 | postgresql://user:pass@host:5432/prod | postgresql://user:pass@host:5432/dev |
BETTER_AUTH_SECRET | Auth 签名密钥 | 随机生成的强密钥 | 同上或独立密钥 |
BETTER_AUTH_URL | Auth 回调基础 URL | https://01mvp.com | https://preview.01mvp.com |
NEXT_PUBLIC_SITE_URL | 站点公开 URL | https://01mvp.com | https://preview.01mvp.com |
S3 存储(必填)
| 变量名 | 说明 |
|---|---|
S3_ENDPOINT | S3 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_KEY | AI API 密钥 | - |
OPENAI_BASE_URL | API 基础 URL | https://api.deepseek.com |
OPENAI_MODEL | 模型名称 | deepseek-v4-flash |
OAuth 登录(按需)
| 变量名 | 说明 |
|---|---|
GOOGLE_CLIENT_ID | Google OAuth Client ID |
GOOGLE_CLIENT_SECRET | Google OAuth Client Secret |
GITHUB_CLIENT_ID | GitHub OAuth Client ID |
GITHUB_CLIENT_SECRET | GitHub OAuth Client Secret |
WECHAT_WEBSITE_APP_ID | 微信网站应用 AppID |
WECHAT_WEBSITE_APP_SECRET | 微信网站应用 AppSecret |
支付(按需)
| 变量名 | 说明 |
|---|---|
STRIPE_SECRET_KEY | Stripe Secret Key |
STRIPE_WEBHOOK_SECRET | Stripe Webhook 签名密钥 |
NEXT_PUBLIC_STRIPE_PRICE_PRO_MONTHLY | 月付价格 ID |
NEXT_PUBLIC_STRIPE_PRICE_PRO_YEARLY | 年付价格 ID |
WAFFO_MERCHANT_ID | Waffo 商户 ID |
WAFFO_PRIVATE_KEY | Waffo 私钥 |
邮件(按需)
| 变量名 | 说明 |
|---|---|
PLUNK_API_KEY | Plunk/Zeabur 邮件 API Key |
EMAIL_FROM | 发件人地址 |
CONTACT_EMAIL | 联系邮箱 |
可选变量
| 变量名 | 说明 |
|---|---|
NEXT_PUBLIC_UMAMI_WEBSITE_ID | Umami 统计 ID |
NEXT_PUBLIC_UMAMI_SCRIPT_URL | Umami 脚本地址 |
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID | Google Analytics ID |
TRUSTED_ORIGINS | CORS 信任源(逗号分隔) |
Production vs Preview 环境差异
| 维度 | Production | Preview |
|---|---|---|
| 数据库 | 生产数据库(独立实例) | 测试数据库或开发库 |
| 域名 | 自定义域名 | *.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-webZeabur 会使用 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 | 本地模拟生产环境时使用 | 否 |
最佳实践
- 敏感变量只在部署平台设置:
DATABASE_URL、BETTER_AUTH_SECRET、API Key 等永远不要出现在代码或 Git 中 - 公开变量用
NEXT_PUBLIC_前缀:这些变量会被打包到客户端 bundle,不包含敏感信息 - 生产环境使用独立数据库:不要让生产环境和开发环境共用同一个数据库
- 定期轮换密钥:
BETTER_AUTH_SECRET泄露后需要重新生成并重新部署 - 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:deploydb: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 都已通过
- 部署后访问首页正常
- 登录注册流程正常
- 核心功能验证通过(参考"部署后验证"章节)