环境变量管理与多环境切换
为什么需要多环境
同一个 Prisma 项目通常会有至少三个环境:
| 环境 | 用途 | 数据库 |
|---|---|---|
| 本地开发 | 写代码、跑测试 | SQLite 文件 或 本地 Docker Postgres |
| CI / Staging | 代码合并前跑集成测试 | 独立的 Postgres 实例 |
| 生产 | 面向真实用户 | 云托管 Postgres/MySQL |
每个环境的 DATABASE_URL 肯定不同。Prisma 的做法是让 URL 变成环境变量,环境变量的值由部署环境注入。
.env 文件查找顺序
Prisma CLI 在执行命令时,按以下顺序加载环境变量文件:
- 当前目录开始往上查找
.env文件(直到根目录) - 加载找到的所有
.env文件(后面的覆盖前面的同名变量) - 如果命令行显式指定了环境变量(
DATABASE_URL=... npx prisma ...),则覆盖文件里的值
所以:默认情况下 npx prisma migrate dev 用的是项目根目录下的 .env。
方式一:命令行覆盖(最简单)
# 显式指定生产数据库 URL 跑迁移
DATABASE_URL="postgresql://prod-user:pass@prod-host:5432/proddb" \
DIRECT_URL="postgresql://prod-user:pass@prod-host:5432/proddb" \
npx prisma migrate deploy
这种方式适合 CI/CD 脚本——CI 系统把密码存在 secrets 里,执行时注入。
方式二:不同 .env 文件 + dotenv CLI
安装 dotenv-cli:
npm install --save-dev dotenv-cli
然后创建多个 .env 文件:
.env.development → DATABASE_URL="postgresql://postgres:pass@localhost:5432/devdb"
.env.staging → DATABASE_URL="postgresql://staging-user:pass@staging-host:5432/stagingdb"
.env.production → DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=xxx"
执行命令时指定:
# 跑 Staging 的迁移
npx dotenv -e .env.staging -- prisma migrate deploy
# 跑生产迁移(危险操作,注意)
npx dotenv -e .env.production -- prisma migrate deploy
可以在 package.json 里加脚本:
{
"scripts": {
"migrate:staging": "dotenv -e .env.staging -- prisma migrate deploy",
"migrate:prod": "dotenv -e .env.production -- prisma migrate deploy"
}
}
方式三:PRISMA_ENV 变量
Prisma v5 起支持通过 PRISMA_ENV 指定加载哪个 .env 文件:
PRISMA_ENV=staging npx prisma migrate deploy
这会让 Prisma 优先加载 .env.staging。但不是所有 Prisma 版本都支持这个特性,推荐还是用 dotenv-cli。
DIRECT_URL 什么时候必需
如果你用了 Prisma Accelerate、PgBouncer、Supavisor 等连接池/代理层:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL") # → 指向连接池
directUrl = env("DIRECT_URL") # → 直连数据库
}
规则:
- 应用运行时 用
DATABASE_URL(经过连接池) - Prisma Migrate、db pull、Studio 等 CLI 命令用
DIRECT_URL(绕过连接池直连)
因为迁移需要创建临时表、锁表等操作,连接池代理可能不支持或有延迟。如果 CLI 没找到 DIRECT_URL,会尝试用 url,连接池场景下可能报错。
典型场景:Vercel + Neon + Accelerate
.env.production:
DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=abc123"
DIRECT_URL="postgresql://neon-prod-user:xxx@ep-xxx-pooler.us-east-2.aws.neon.tech/neondb"
- 应用运行走 Accelerate(
DATABASE_URL),获得连接池和查询缓存 - 迁移走 Neon 直连(
DIRECT_URL),绕过代理层
生产环境环境变量注入方式
| 平台 | 怎么注入 |
|---|---|
| Vercel / Netlify | 项目 Settings → Environment Variables UI |
| Railway / Render | 项目 Variables UI |
| Docker | docker run --env-file .env.production 或 docker-compose 的 environment: |
| Kubernetes | Secret / ConfigMap 挂载到 Pod |
| GitHub Actions | Repository Secrets → ${{ secrets.DATABASE_URL }} |
| 裸机 systemd | EnvironmentFile=/etc/myapp/.env 或 Environment="DATABASE_URL=..." |
.gitignore
确保以下文件不会被提交到 Git:
# .gitignore
.env
.env.local
.env.*.local
# 例外:可以把格式模板提交上去
.env.example
.env.development.example
.env.example 应该只有占位值,告诉其他开发者需要哪些变量:
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
DIRECT_URL="postgresql://user:password@localhost:5432/mydb"