01MVP 标识01MVP
开发指南部署指南

部署指南

Mono monorepo 在 Zeabur、Docker 和生产数据库上的部署方式

Mono 是一个 pnpm workspace + Turborepo monorepo。生产部署时推荐显式使用 Dockerfile,而不是依赖平台的默认 monorepo 自动识别。

推荐策略

当前仓库推荐的生产部署方式:

  • Zeabur + Dockerfile:每个 app 一个独立服务,平台直接构建指定 Dockerfile
  • 根目录构建,按 app 裁剪:通过 turbo prune --docker 只保留目标应用和必要 workspace 依赖
  • 运行时环境变量分离:每个服务单独维护环境变量,不在仓库里硬编码生产密钥

为什么不用默认的 Node.js Monorepo 自动识别

Zeabur 的 monorepo 自动识别可以帮助发现应用,但它不能替代显式 Docker 部署:

  • ZBPACK_APP_DIR 只能告诉 Zeabur 把哪个目录当成 Node.js 项目
  • 它不会自动帮你选择正确的 Dockerfile
  • 直接在整个 monorepo 上执行 pnpm install 会安装完整 workspace,构建比实际需要更重
  • turbo prune --docker 可以把镜像构建范围收缩到单个 app 及其真实依赖

仓库中的 Dockerfile 约定

根目录使用 Dockerfile.[service] 命名:

  • Dockerfile.mono-web:部署 apps/mono-web
  • Dockerfile.timemark:部署 apps/timemark

每个 Dockerfile 都遵循同一套路:

  1. 在仓库根目录执行 turbo prune --docker
  2. 只安装裁剪后 workspace 的依赖
  3. 构建 Next.js standalone 输出
  4. 使用更小的运行时镜像启动服务

Zeabur 部署 mono-web

1. 创建服务

在 Zeabur 中为 mono-web 单独创建一个服务:

  1. 新建项目或进入现有项目
  2. 连接 GitHub 仓库 01mvp/mono
  3. 保持工作目录为仓库根目录
  4. 启用 Dockerfile 部署

2. 配置服务变量

最关键的变量是:

ZBPACK_DOCKERFILE_NAME=mono-web

如果之前为了平台自动识别设置过 ZBPACK_APP_DIR,在切到 Dockerfile 部署后通常可以移除;保留为 / 也不会影响构建,但没有必要继续依赖它。

3. 配置运行时环境变量

至少需要补齐应用运行依赖的环境变量,常见示例:

DATABASE_URL=postgresql://...
BETTER_AUTH_SECRET=...
BETTER_AUTH_URL=https://your-domain.com
NEXT_PUBLIC_SITE_URL=https://your-domain.com
S3_ENDPOINT=...
S3_REGION=...
S3_ACCESS_KEY_ID=...
S3_SECRET_ACCESS_KEY=...
S3_BUCKET=...
NEXT_PUBLIC_S3_ENDPOINT=...
OPENAI_API_KEY=...
OPENAI_BASE_URL=...
OPENAI_MODEL=...

具体必填项以 配置说明 为准。

4. 触发部署

推送到绑定分支后,Zeabur 会在仓库根目录找到 Dockerfile.mono-web 并开始构建。

推荐检查点:

  • 构建日志中是否出现 turbo prune --docker
  • Next.js 是否以 standalone 方式输出
  • 运行阶段是否成功读取 DATABASE_URL 和鉴权变量

Zeabur 如何匹配 Dockerfile

Zeabur 支持以下根目录命名模式:

  • Dockerfile
  • [service].Dockerfile
  • Dockerfile.[service]

本仓库采用 Dockerfile.[service],因此:

  • ZBPACK_DOCKERFILE_NAME=mono-web 对应 Dockerfile.mono-web
  • ZBPACK_DOCKERFILE_NAME=timemark 对应 Dockerfile.timemark

即使 Zeabur 服务名和后缀相同,仍建议显式设置 ZBPACK_DOCKERFILE_NAME,避免后续重命名服务时引入隐式耦合。

多应用部署

同一个 monorepo 可以在 Zeabur 中部署多个服务,但每个服务都应该独立配置:

服务Dockerfile 变量说明
mono-webZBPACK_DOCKERFILE_NAME=mono-web主站和文档站
timemarkZBPACK_DOCKERFILE_NAME=timemarkTimemark 应用

每个服务共享同一个 Git 仓库,但拥有各自的域名、环境变量和部署历史。

Docker 本地与生产部署

本地验证

cp apps/mono-web/.env.example apps/mono-web/.env.local
docker compose up -d
docker compose logs -f

手动构建镜像

docker build -f Dockerfile.mono-web -t mono-web .
docker run -d \
  --env-file apps/mono-web/.env.production \
  -p 3000:3000 \
  mono-web

环境变量文件

文件用途说明
apps/mono-web/.env.local本地开发不提交到 Git
apps/mono-web/.env.production生产运行仅在部署平台或安全环境中使用

数据库与迁移

生产数据库推荐:

  • Zeabur PostgreSQL:与部署平台集成,一键创建
  • Neon:Serverless PostgreSQL,适合低成本起步

数据库变更请使用迁移,不要直接在生产库上做临时变更:

pnpm db:migrate

如果 Prisma schema 有变化,部署前先确认已经执行并提交了对应 migration。

域名和可观测性

域名

在 Zeabur 服务设置中绑定自定义域名,并在 DNS 提供商侧配置对应记录。

数据分析

项目使用 Umami 进行访问统计。

当前公开统计看板:

部署检查清单

  • Zeabur 服务工作目录保持在仓库根目录
  • 已设置 ZBPACK_DOCKERFILE_NAME=mono-web
  • 运行时环境变量已补齐
  • 数据库 migration 已提交并可执行
  • 自定义域名和 NEXT_PUBLIC_SITE_URL 保持一致
  • 构建日志确认使用了裁剪后的 workspace