2026-02-17•ToolBox Team
环境变量与应用配置最佳实践
🔧 返回工具箱 | Back to Tools
浏览所有工具 | View All Toolsconfigurationenvironmentdevopssecurity
环境变量与应用配置最佳实践
一个优秀的应用应该能够在开发、测试、生产等不同环境中无缝运行。环境变量是实现这一目标的关键机制。从敏感的数据库密码到功能开关,环境变量为应用的灵活性和安全性奠定基础。
1. 为什么使用环境变量?
问题:代码中硬编码配置
// ❌ 绝对禁止
const DATABASE_URL = 'postgres://user:password@localhost:5432/db';
const API_SECRET = 'super-secret-key-12345';
const DEBUG = true;
// 问题:
// 1. 敏感信息被 commit 到 Git
// 2. 代码库泄露 = 生产凭证泄露
// 3. 开发、测试、生产使用同一套配置
// 4. 每次环境切换都要修改代码
解决方案:环境变量
// ✅ 正确做法
const DATABASE_URL = process.env.DATABASE_URL || 'postgres://localhost:5432/dev_db';
const API_SECRET = process.env.API_SECRET;
const DEBUG = process.env.DEBUG === 'true';
if (!API_SECRET) {
throw new Error('缺少必需的环境变量: API_SECRET');
}
2. 环境变量的来源
Linux/macOS 设置
# 临时设置(仅当前 shell 会话)
export DB_HOST=localhost
export DB_PORT=5432
# 验证
echo $DB_HOST # localhost
# 在命令前设置
DB_HOST=localhost npm start
Windows 设置
REM 临时设置(仅当前 cmd 会话)
set DB_HOST=localhost
REM 永久设置(重启后仍有效)
setx DB_HOST localhost
.env 文件(推荐开发阶段)
创建 .env 文件:
# 数据库配置
DATABASE_URL=postgres://user:password@localhost:5432/myapp_dev
DATABASE_POOL_SIZE=10
# API 密钥
API_SECRET=dev-secret-key-abc123
JWT_SECRET=jwt-dev-secret-xyz789
# 特性开关
DEBUG=true
LOG_LEVEL=debug
ENABLE_CACHE=false
# 邮件服务
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=dev@example.com
SMTP_PASS=app-password
使用 dotenv 加载 .env
// 安装:npm install dotenv
require('dotenv').config();
console.log(process.env.DATABASE_URL);
console.log(process.env.API_SECRET);
重要:.env 文件应该被加入 .gitignore,永远不要上传到版本控制!
# .gitignore
.env
.env.local
.env.*.local
.env.example(版本控制)
创建示例文件供其他开发者参考:
# .env.example
DATABASE_URL=postgres://user:password@localhost:5432/myapp_dev
DATABASE_POOL_SIZE=10
API_SECRET=your-api-secret-here
JWT_SECRET=your-jwt-secret-here
DEBUG=false
LOG_LEVEL=info
ENABLE_CACHE=true
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@example.com
SMTP_PASS=your-app-password
3. Node.js 应用中的最佳实践
配置管理类
// config/index.js
require('dotenv').config();
const config = {
// 应用
env: process.env.NODE_ENV || 'development',
port: parseInt(process.env.PORT || '3000', 10),
// 数据库
database: {
url: process.env.DATABASE_URL,
pool: {
min: parseInt(process.env.DB_POOL_MIN || '5', 10),
max: parseInt(process.env.DB_POOL_MAX || '20', 10),
},
},
// 认证
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN || '24h',
},
// 特性开关
features: {
cache: process.env.ENABLE_CACHE === 'true',
analytics: process.env.ENABLE_ANALYTICS === 'true',
},
// 日志
logging: {
level: process.env.LOG_LEVEL || 'info',
},
};
// 验证必需环境变量
const required = ['DATABASE_URL', 'JWT_SECRET'];
for (const key of required) {
if (!process.env[key]) {
throw new Error(`缺少必需的环境变量: ${key}`);
}
}
module.exports = config;
在应用中使用
// app.js
const config = require('./config');
const express = require('express');
const app = express();
// 使用配置
if (config.logging.level === 'debug') {
app.use(express.json({ limit: '50mb' }));
}
// 数据库连接
const pool = new Pool({
connectionString: config.database.url,
min: config.database.pool.min,
max: config.database.pool.max,
});
// 启动服务
app.listen(config.port, () => {
console.log(`应用运行在端口 ${config.port},环境: ${config.env}`);
});
4. 不同环境的配置
文件结构
config/
├── index.js # 主配置
├── development.js # 开发环境
├── test.js # 测试环境
└── production.js # 生产环境
分环境配置
// config/development.js
module.exports = {
database: {
url: 'postgres://user:password@localhost:5432/app_dev'
},
logging: {
level: 'debug'
},
cache: {
ttl: 300 // 5 分钟缓存
}
};
// config/production.js
module.exports = {
database: {
url: process.env.DATABASE_URL, // 从环境变量读取
ssl: true,
maxConnections: 100
},
logging: {
level: 'warn'
},
cache: {
ttl: 3600 // 1 小时缓存
}
};
// config/index.js
const env = process.env.NODE_ENV || 'development';
const envConfig = require(`./${env}.js`);
module.exports = {
env,
...envConfig
};
5. 敏感信息的安全处理
🔴 永远不要在代码或日志中暴露敏感信息
// ❌ 错误:日志中包含敏感信息
console.log('连接到数据库:', config.database.url);
// 输出:连接到数据库: postgres://user:password@localhost:5432/app
// ✅ 正确:只记录脱敏信息
console.log('数据库连接池已创建,最大连接数:', config.database.pool.max);
密钥管理工具
在生产环境,使用专门的密钥管理服务而非环境变量:
// AWS Secrets Manager
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();
async function getDatabasePassword() {
const secret = await secretsManager.getSecretValue({
SecretId: 'prod/database/password'
}).promise();
return JSON.parse(secret.SecretString).password;
}
// Google Cloud Secret Manager
const { SecretManagerServiceClient } = require('@google-cloud/secret-manager');
async function getApiKey() {
const client = new SecretManagerServiceClient();
const [version] = await client.accessSecretVersion({
name: 'projects/123456/secrets/api-key/versions/latest',
});
return version.payload.data.toString('utf8');
}
Docker 中的敏感信息
# ❌ 不要在 Dockerfile 中硬编码密钥
ARG API_KEY=super-secret-key
RUN echo "API_KEY=$API_KEY" >> /app/.env
# ✅ 通过构建时参数或运行时环境变量传入
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm ci --only=production
# 在运行时传递环境变量
CMD ["node", "app.js"]
运行时传入:
docker run \
-e DATABASE_URL='postgres://...' \
-e API_SECRET='...' \
-e JWT_SECRET='...' \
myapp:latest
使用 Docker Compose 与 .env 文件:
version: '3.8'
services:
app:
image: myapp:latest
env_file: .env
environment:
- NODE_ENV=production
6. Kubernetes 中的配置
# configmap.yaml - 非敏感配置
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info"
DATABASE_POOL_SIZE: "20"
---
# secret.yaml - 敏感信息
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
DATABASE_URL: "postgres://user:pass@host:5432/db"
API_SECRET: "secret-key-abc123"
JWT_SECRET: "jwt-secret-xyz"
---
# deployment.yaml - 使用配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secrets
env:
- name: NODE_ENV
value: "production"
7. 配置验证与日志
启动检查
// config-validator.js
const isProduction = process.env.NODE_ENV === 'production';
const requiredEnvVars = [
'DATABASE_URL',
'JWT_SECRET',
'API_SECRET'
];
const requiredInProduction = [
'SMTP_HOST',
'SMTP_USER',
'SMTP_PASS',
];
function validateConfig() {
const missing = [];
// 检查必需环境变量
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
missing.push(envVar);
}
}
// 在生产环境检查额外的变量
if (isProduction) {
for (const envVar of requiredInProduction) {
if (!process.env[envVar]) {
missing.push(envVar);
}
}
}
if (missing.length > 0) {
throw new Error(`缺少必需的环境变量: ${missing.join(', ')}`);
}
console.log('✓ 配置验证成功');
}
module.exports = { validateConfig };
配置管理清单
在部署到生产前检查:
- 所有敏感信息都在环境变量中,不在代码中
-
.env文件在.gitignore中 - 提供
.env.example供开发者参考 - 敏感信息不会出现在日志中
- 应用在启动时验证所有必需的环境变量
- 为不同环境提供不同的配置
- 使用密钥管理服务而非纯环境变量(生产)
- 文档说明需要的所有环境变量及其含义
相关工具推荐: