Docker 部署

用 Dockerfile 部署到 Zeabur、自有服务器或容器平台。

Docker 部署适合需要自管运行时镜像的场景,例如自有 VPS、K8s,或团队已经有统一容器平台。01MVP 默认生产部署可以直接看 Zeabur 部署

Docker 路径会使用 Next.js standalone 输出。生产密钥优先在运行时注入,不要把真实密钥写入镜像层或提交到仓库。

Zeabur Docker 模式

连接仓库

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

配置构建

在服务设置中:

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

Zeabur 会使用仓库根目录的 Dockerfile.01mvp-web 构建镜像。完整的变量同步、域名和 Cloudflare 配置见 Zeabur 部署

配置运行时环境变量

在 Zeabur 服务的 "Variables" 页面添加生产环境变量。变量名与部署指南一致。

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

绑定域名

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

部署并验证

触发部署,等待构建完成。检查服务日志确认 Next.js server 启动正常,再按部署后验证逐项检查。

自建服务器部署

适用于自有 VPS、K8s 或其他容器平台。

构建镜像

在仓库根目录执行:

docker build -f Dockerfile.01mvp-web -t 01mvp-web:latest \
  --build-arg DATABASE_URL="postgresql://..." \
  --build-arg BETTER_AUTH_SECRET="build-placeholder-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="build-placeholder-access-key" \
  --build-arg S3_SECRET_ACCESS_KEY="build-placeholder-secret-key" \
  --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="build-placeholder-openai-key" \
  --build-arg OPENAI_BASE_URL="https://api.deepseek.com" \
  --build-arg OPENAI_MODEL="deepseek-v4-flash" \
  .

--build-arg 会进入构建历史和缓存。真实生产密钥应在运行容器时通过环境变量、平台 Secret 或 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" \
  -e OPENAI_API_KEY="your-key" \
  01mvp-web:latest

容器暴露端口 7001,运行命令为:

node apps/01mvp-web/server.js

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
      - OPENAI_API_KEY=your-key
    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:

Dockerfile 构建流程

Dockerfile.01mvp-web 的构建流程如下:

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

安装裁剪后 workspace 的依赖。

执行 pnpm --filter 01mvp-web run build:docker,生成 Next.js standalone 输出。

使用 node:24-slim 作为运行时镜像,以非 root 用户启动服务。

生产迁移

Docker 部署不要把数据库迁移放进镜像 build。推荐在启动新版本前单独执行:

cd apps/01mvp-web
DATABASE_URL="postgresql://user:pass@host:5432/prod?sslmode=require" \
  pnpm db:deploy

如果你在生产机器内执行,先确认当前 shell 连接的是生产库:

node -e 'const u=new URL(process.env.DATABASE_URL); console.log(u.host, u.pathname)'

常见问题

上线检查

  • 镜像使用 Dockerfile.01mvp-web 构建
  • 生产密钥通过运行时环境变量注入
  • 容器端口 7001 已映射到外部入口
  • BETTER_AUTH_URLNEXT_PUBLIC_SITE_URL 指向生产域名
  • 生产 migration 已在部署前执行
  • 容器日志无启动错误
  • 域名、HTTPS、登录、上传和邮件已验证