Prisma 中文文档 下载 App

生产环境部署清单:Vercel、Docker、PM2

五个必选项

部署到生产环境时,不管什么平台,都要回答这五个问题:

  1. 迁移什么时候跑? (不是在每次函数启动时!)
  2. DATABASE_URL 和 DIRECT_URL 怎么配?
  3. 生产 PrismaClient 要不要关掉 query 日志?
  4. 连接池大小和数据库的连接上限对得上吗?
  5. 应用崩溃/重启时 PrismaClient 怎么优雅关闭?

方案一:Vercel(Serverless)

架构

Vercel Build Step(跑 migrate deploy + prisma generate)
  → Vercel Functions(每个函数实例是一个 Serverless Runtime)
  → 数据库(PostgreSQL/MySQL/SQLite)

配置步骤

1. 环境变量(在 Vercel Project Settings → Environment Variables):

DATABASE_URL=prisma://accelerate.prisma-data.net/?api_key=xxx   # 或直连
DIRECT_URL=postgresql://user:pass@real-host:5432/proddb         # migrate 用

2. Build Command / Pre-build Command:

# Vercel Pre-build Command(Build Phase 前执行一次)
npx prisma migrate deploy

# Build Command
npx prisma generate && next build  # 或你的构建命令

Pre-build Command 比每个函数里自动跑更高效——它只跑一次,而不是每个冷启动的函数实例都跑。

3. 生产 PrismaClient:

export const prisma = new PrismaClient({
  log: ['error'],  // 只记 error,关掉 query 日志
})

坑点

方案二:Docker + 云服务器(长驻进程)

Dockerfile

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY prisma ./prisma
RUN npx prisma generate
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/package.json ./

# 容器启动时:先跑迁移,再启动应用
CMD ["sh", "-c", "npx prisma migrate deploy && npm start"]

docker-compose 简化版

services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

  app:
    build: .
    environment:
      DATABASE_URL: postgresql://postgres:secret@db:5432/mydb?schema=public
      DIRECT_URL: postgresql://postgres:secret@db:5432/mydb?schema=public
    depends_on:
      - db

volumes:
  pgdata:

Docker Compose 启动顺序不可靠(app 启动时 db 可能还没 ready),migrate deploy 有数据库连不上时的重试逻辑,刚好能 cover。

方案三:PM2 / systemd(裸机或 VM)

# 部署脚本
cd /var/www/myapp
git pull origin main
npm ci
npx prisma migrate deploy
npm run build
pm2 restart myapp

PM2 或 systemd 管理的长驻进程不需要额外关心 PrismaClient 的生命周期——它跟进程同生共死。进程崩溃重启时 PrismaClient 也会跟着重新创建。

PM2 优雅关闭

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'myapp',
    script: 'dist/server.js',
    listen_timeout: 10000,
    kill_timeout: 10000,  // 给足够时间让 Prisma $disconnect() 完成
  }],
}

在应用代码里监听 SIGINT/SIGTERM:

process.on('SIGINT', async () => {
  console.log('正在关闭...')
  await prisma.$disconnect()
  process.exit(0)
})

生产 PrismaClient 配置

// src/lib/prisma.ts(生产版)
import { PrismaClient } from '@prisma/client'

export const prisma = new PrismaClient({
  log: ['error'],  // 关掉 query 日志,只记 error
  // production 不做热重载,不需要 globalThis 单例
})

生产环境与开发环境的 PrismaClient 区别:

配置开发生产
log['query', 'error', 'warn']['error']
单例方式globalThis 跨 HMR直接 new 一次
端口/主机localhost按部署环境

环境变量管理

生产环境的 .env 绝对不要提交到 Git。推荐做法:

部署前自检清单