
文章摘要: 本文是一份全面的 Node.js 环境变量配置指南。我们将从环境变量的基本概念讲起,逐步深入到如何在开发、测试、生产及 Docker 环境中高效、安全地管理配置。通过实战代码示例,您将掌握 process.env、dotenv、环境配置验证等核心技能,并了解在现代化部署流程中的最佳实践。
一、 引言:为什么需要环境变量?
-
配置与代码分离
-
问题:将数据库连接字符串、API密钥等硬编码在代码中的危害。
-
好处:提高代码安全性、可移植性和可维护性。
-
-
多环境适配
-
场景:开发、测试、预发布、生产环境需要不同的配置。
-
目标:一套代码,通过不同环境变量适配不同场景。
-
-
安全合规
-
避免敏感信息泄露到代码仓库。
-
符合现代安全和 DevOps 流程的基本要求。
-
二、 Node.js 中的基础:process.env
-
什么是
process.env?- 全局对象,包含用户环境的键值对。
-
如何访问环境变量?
javascript
const apiKey = process.env.API_KEY; const port = process.env.PORT || 3000; // 设置默认值 -
如何设置环境变量?
-
临时设置(命令行):
bash
API_KEY=your_secret_key node app.js -
持久化设置(系统级):
-
Linux/macOS:
export API_KEY=value(添加到~/.bashrc或~/.zshrc) -
Windows:
set API_KEY=value(命令行) 或通过系统属性设置。
-
-
三、 开发环境实战:使用 dotenv 包
-
为什么需要
dotenv?- 解决开发阶段手动设置大量环境变量的繁琐问题。
-
安装与基本使用
bash
npm install dotenv- 在项目根目录创建
.env文件:
text
NODE_ENV=development DATABASE_URL=postgresql://user:pass@localhost:5432/mydb API_SECRET=my_dev_secret JWT_SECRET=my_jwt_secret- 在应用入口文件(如
app.js)的最顶部加载:
javascript
require('dotenv').config(); // 默认加载 .env 文件 // 现在 process.env 中包含了 .env 文件里定义的变量 console.log(process.env.NODE_ENV); // 'development' - 在项目根目录创建
-
高级配置
-
指定自定义路径:
require('dotenv').config({ path: '/path/to/.env' }); -
重要:将
.env添加到.gitignore,防止敏感信息提交。
-
四、 生产环境与多环境管理
-
区分环境:
NODE_ENV变量-
标准值:
development,test,production。 -
框架(如 Express)会根据此变量改变行为(例如,开启缓存、压缩)。
-
-
生产环境如何设置变量?
-
云平台/托管服务(Vercel, Netlify, Heroku, AWS Elastic Beanstalk): 在平台提供的管理界面中配置。
-
服务器(Linux): 使用 Systemd 服务文件、
~/.profile或通过 CI/CD 流程注入。 -
Docker: 使用
-e标志或docker-compose.yml中的environment部分。
-
-
多环境
.env文件模式-
创建多个文件:
.env.development,.env.production,.env.test。 -
根据
NODE_ENV动态加载:
javascript
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });- 注意: 此模式主要用于开发/测试便利,生产环境仍应直接设置系统环境变量。
-
五、 进阶实战与模式
-
配置模块化与验证
-
问题: 环境变量缺失或格式错误会导致运行时隐蔽错误。
-
解决方案: 创建
config.js模块,进行集中管理和验证。
javascript
// config.js const Joi = require('joi'); // 使用 Joi 进行 schema 验证 // 定义环境变量 schema const envVarsSchema = Joi.object({ NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'), PORT: Joi.number().default(3000), DATABASE_URL: Joi.string().required(), API_SECRET: Joi.string().required().min(32), }).unknown(); // 允许其他未定义的变量 const { value: envVars, error } = envVarsSchema.validate(process.env); if (error) { throw new Error(`Config validation error: ${error.message}`); } module.exports = { env: envVars.NODE_ENV, port: envVars.PORT, database: { url: envVars.DATABASE_URL, }, api: { secret: envVars.API_SECRET, }, };- 在应用中使用:
const config = require('./config');
-
-
TypeScript 环境下的类型安全
-
创建
config.ts,使用接口定义配置结构。 -
使用
zod等库进行验证和类型推断。
-
-
在 Docker 中使用环境变量
Dockerfile示例:
dockerfile
FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . # 通过 docker run -e 传入变量 CMD ["node", "app.js"]docker-compose.yml示例:
yaml
services: app: build: . ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=${DATABASE_URL} # 从宿主机环境变量读取 env_file: - .env.production # 或者从文件读取(不推荐用于生产机密)
六、 安全最佳实践
-
永远不要提交
.env文件 -
为不同环境使用不同的密钥
- 开发、测试、生产环境的数据库和 API 密钥必须隔离。
-
生产环境机密管理
-
使用专门的机密管理服务:AWS Secrets Manager, Azure Key Vault, HashiCorp Vault。
-
避免在日志中打印环境变量。
-
-
定期轮换密钥
- 建立流程,定期更新数据库密码、API 密钥等。
七、 常见问题与故障排除
-
process.env返回undefined?-
检查变量名拼写。
-
确认
.env文件已正确加载且路径正确。 -
在生产环境确认变量已在平台正确设置。
-
-
.env文件不生效?-
确保
dotenv在代码最顶部加载。 -
检查
.env文件格式(无空格,无引号)。
-
-
如何在 PM2 中使用?
- 使用 PM2 的
ecosystem.config.js文件:
javascript
module.exports = { apps: [{ name: 'my-app', script: './app.js', env: { NODE_ENV: 'development', }, env_production: { NODE_ENV: 'production', } }] }; - 使用 PM2 的
八、 总结
-
核心思想: 配置与代码分离,环境隔离。
-
开发利器:
dotenv+.env文件。 -
生产基石: 系统环境变量 + 云平台配置/机密管理服务。
-
质量保障: 配置验证与模块化。
-
安全底线: 保护密钥,永不入仓。
通过遵循本指南,您可以构建一个健壮、安全且易于维护的 Node.js 应用程序配置系统。