Docker 部署
用 Dockerfile 部署到 Zeabur、自有服务器或容器平台。
Docker 部署适合需要自管运行时镜像的场景,例如自有 VPS、K8s,或团队已经有统一容器平台。01MVP 默认生产部署可以直接看 Zeabur 部署。
Docker 路径使用 Vite Plus 构建 @01mvp/web,并运行 products/01mvp/apps/web/dist 生产产物。生产密钥优先在运行时注入,不要把真实密钥写入镜像层或提交到仓库。
Zeabur Docker 模式
连接仓库
在 Zeabur 控制台创建服务,连接 Git 仓库。
配置构建
在服务设置中:
- 工作目录设为仓库根目录
- 启用 Dockerfile 部署模式
- 设置环境变量:
ZBPACK_APP_DIR=products/01mvp/apps/web
ZBPACK_DOCKERFILE_NAME=DockerfileZeabur 会使用仓库根目录的 Dockerfile 构建镜像。完整的变量同步、域名和 Cloudflare 配置见 Zeabur 部署。
在 Zeabur Variables 中用平台域名变量生成公开 URL,不要把某个固定站点写进镜像:
VITE_WEB_URL=https://${ZEABUR_WEB_DOMAIN}
VITE_SERVER_URL=https://${ZEABUR_WEB_DOMAIN}/apiZEABUR_WEB_DOMAIN 是域名本身,不带协议和尾部斜杠;Dockerfile 在没有显式 VITE_WEB_URL 时也会用它生成构建期 URL。
配置运行时环境变量
在 Zeabur 服务的 "Variables" 页面添加生产环境变量。变量名与部署指南一致。
Zeabur 提供的内置变量如 PORT 会自动注入,无需手动配置。VITE_WEB_URL 和 VITE_SERVER_URL 需要同时存在于构建期和运行时,因为前端包会在构建时读取它们,服务端登录、邮件和回调也会在运行时读取它们。
绑定域名
在 Zeabur 服务的 "Networking" 页面绑定自定义域名,并在 DNS 侧配置 CNAME 指向 Zeabur 提供的地址。
部署并验证
触发部署,等待构建完成。检查服务日志确认 TanStack Start server 启动正常,再按部署后验证逐项检查。
自建服务器部署
适用于自有 VPS、K8s 或其他容器平台。
构建镜像
在仓库根目录执行:
docker build -f Dockerfile -t 01mvp-start:latest \
--build-arg VITE_WEB_URL="https://your-domain.com" \
--build-arg VITE_SERVER_URL="https://your-domain.com/api" \
--build-arg DATABASE_URL="postgresql://postgres:postgres@localhost:5432/build-placeholder" \
--build-arg BETTER_AUTH_SECRET="replace-with-at-least-32-characters" \
.--build-arg 会进入构建历史和缓存。这里的 DATABASE_URL 和 BETTER_AUTH_SECRET 只用于构建期校验,占位值即可;真实生产密钥应在运行容器时通过环境变量、平台 Secret 或 docker buildx build --secret 注入。
如果构建平台提供 ZEABUR_WEB_DOMAIN,Dockerfile 可以从它推导 VITE_WEB_URL 和 VITE_SERVER_URL;自建服务器没有这个变量时必须显式传入上面的两个 build arg。
运行容器
docker run -d \
--name 01mvp-start \
-p 7001:7001 \
-e DATABASE_URL="postgresql://..." \
-e BETTER_AUTH_SECRET="your-secret" \
-e VITE_WEB_URL="https://your-domain.com" \
-e VITE_SERVER_URL="https://your-domain.com/api" \
-e OPENAI_API_KEY="your-key" \
-e OPENAI_BASE_URL="https://api.deepseek.com" \
-e OPENAI_MODEL="deepseek-v4-flash" \
01mvp-start:latest容器默认监听 7001,平台也可以通过 PORT 覆盖。运行命令为:
node /app/products/01mvp/apps/web/scripts/start-node.mjsdocker-compose 参考
先从 .env.docker.example 复制一份 .env.docker,把域名、数据库和密钥换成当前环境的值。
services:
01mvp-start:
build:
context: .
dockerfile: Dockerfile
ports:
- "7001:7001"
env_file:
- .env.docker
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 的构建流程如下:
安装 Vite Plus Linux CLI,并复制 package.json、pnpm-lock.yaml、pnpm-workspace.yaml 以及各 workspace 的 package.json。
执行 vp install --frozen-lockfile --ignore-scripts,让依赖层可以被 Docker 缓存。
复制完整源码,执行 vpr @01mvp/web#build(或根目录短写 vpr @01mvp/web#build),生成 products/01mvp/apps/web/dist/server 和 products/01mvp/apps/web/dist/client。
使用 node:24-slim 作为运行时镜像,复制 products/01mvp/apps/web/dist、启动脚本、依赖和数据库 migration 文件,以非 root 用户启动服务。
生产迁移
Docker 部署不要把数据库迁移放进镜像 build。当前模板默认使用显式迁移:部署生产容器前运行 vpr @01mvp/product#db:deploy,执行已经提交的 migration 文件。
如果你在生产机器内执行,先确认当前 shell 连接的是生产库:
node -e 'const u=new URL(process.env.DATABASE_URL); console.log(u.host, u.pathname)'常见问题
上线检查
- 镜像使用
Dockerfile构建 - 生产密钥通过运行时环境变量注入
- 容器端口
7001已映射到外部入口 -
VITE_WEB_URL和VITE_SERVER_URL指向生产域名 - 生产 migration 文件已提交,启动日志无迁移失败
- 容器日志无启动错误
- 域名、HTTPS、登录、上传和邮件已验证
这篇文档有问题?