Dotenvx 配置示例
Dotenvx 配置示例
基础配置示例
.env (开发环境默认配置)
# 应用配置
NODE_ENV=development
PORT=3000
APP_NAME=MyApp
APP_VERSION=1.0.0
# 数据库配置
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp_dev
DB_USER=developer
DB_PASSWORD=dev123
# Redis 配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
# API 配置
API_BASE_URL=http://localhost:3000/api
JWT_SECRET=dev-secret-key
JWT_EXPIRES_IN=24h
# 第三方服务
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
SENDGRID_API_KEY=SG.test...
# 日志配置
LOG_LEVEL=debug
LOG_FORMAT=combined
# 功能开关
FEATURE_NEW_UI=true
FEATURE_ANALYTICS=false
.env.production (生产环境加密配置)
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY_PRODUCTION="026d4945b6513baec60f68b207f203ba534fb54d2b0c9952557d240815e42a7d83"
# 应用配置
NODE_ENV="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
PORT="encrypted:BGcRf5bK/mChGEqT1MZ8hUbMm3hhtuW9NVGkHtl7KRwqbSKnVcGIDs9T61u77DlyNlYcF1BlLCw9HPmbRQ0nFvLOCZc6r42iRE4OyJw9mu61OjlWQfEl5Z1NrjZw5g0d1tp8New="
APP_NAME="encrypted:BBrXv55qxgA19sEqqNnZzS/C0WguVk6ROQmfxnGhBhafLoc0XwpKprk/J3hJCVq7s45WyBSXGUz9U9rHxCBeVkl27WFzzgZkDewX0gBLt+Cc37K0EVU2hZ1GPbax5mzpI5Jwwi65be6+"
# 数据库配置
DB_HOST="encrypted:BMO83g2fEtr66gcFvUs2+/ZuccCQuBbZwSW3JfCLvoUiACmusxCbTfG2dvc2LxenPhUtgWapO8f9BCcBVAcTnMcrd3kndvk+acWytRjIWRUvsSezdD340/OT5EQgbqJtwXfuRz0i2t8PVA=="
DB_PORT="encrypted:BGcRf5bK/mChGEqT1MZ8hUbMm3hhtuW9NVGkHtl7KRwqbSKnVcGIDs9T61u77DlyNlYcF1BlLCw9HPmbRQ0nFvLOCZc6r42iRE4OyJw9mu61OjlWQfEl5Z1NrjZw5g0d1tp8New="
DB_NAME="encrypted:BL0icNnZh6InVmymJBCX6MuL6cwgVc4v1ua1g1XONlV7nkzzHHHpnZN3khx7+ld15bd88EtV4DfqUV2eJ/HJwu0/5F1MH+PAisYSRxBQo8I9AHly2sRsonBm3Bji+DslcC4D7b7wLTBlfCw="
DB_USER="encrypted:BBrXv55qxgA19sEqqNnZzS/C0WguVk6ROQmfxnGhBhafLoc0XwpKprk/J3hJCVq7s45WyBSXGUz9U9rHxCBeVkl27WFzzgZkDewX0gBLt+Cc37K0EVU2hZ1GPbax5mzpI5Jwwi65be6+"
DB_PASSWORD="encrypted:BC8aRBQ/Q2YMPjJayggqVN8skqTtxtXFgYA0e8/Ud/Jcez2Daukr6edBmEWQdz/Lu91casaW6CkkCvLSQkPvNpmgYqFB4BKHTUDowX/KEDvVI6CU5Vt478VF5dqHbvPIoKKtBe+4FNXlk5O96A=="
# Redis 配置
REDIS_HOST="encrypted:BMVEIPBGe9xkELFb48KQJPxxnTkUGhsonAU4ug5ca9E5eD/MZimkoQrf/3cb9nhazwfTbScLgeGGr/Jhj4DV7Xpz45XEEFWrPXy1Yi93zWLaJ4XYBHwCke3b4XCbh7jV4uL3WWFjI757yTIS6ilD"
REDIS_PORT="encrypted:BGcRf5bK/mChGEqT1MZ8hUbMm3hhtuW9NVGkHtl7KRwqbSKnVcGIDs9T61u77DlyNlYcF1BlLCw9HPmbRQ0nFvLOCZc6r42iRE4OyJw9mu61OjlWQfEl5Z1NrjZw5g0d1tp8New="
REDIS_PASSWORD="encrypted:BIgpV7btyiGYyySYnG3+NJVGUzNzB4zWjIZbM/VgtnPuiuSsK/KBkirtqkDBI8U/04BRKtupOTNSJTVu6GO39XPSpPvlxA4fNRyeK85W+rFGARp4mrgqfEz/O/eZvqJSqS5kNraAhbkKpXq81rEOBg=="
# API 配置
API_BASE_URL="encrypted:BMVEIPBGe9xkELFb48KQJPxxnTkUGhsonAU4ug5ca9E5eD/MZimkoQrf/3cb9nhazwfTbScLgeGGr/Jhj4DV7Xpz45XEEFWrPXy1Yi93zWLaJ4XYBHwCke3b4XCbh7jV4uL3WWFjI757yTIS6ilD"
JWT_SECRET="encrypted:BCrnJ2sAZH2qwRlPvUqqWyEsd+cVeMQiOV5H/xZ7vjFfcMXHMunmAv/7+jUI356fkVtHfrXu+vBJLjXJiirgB2gky5vvy7h5jevgMS6BgPL5KwjC0tYPlYbe4Bfrf1funYqqrFYaPjsEO+77vCtVaBPz"
JWT_EXPIRES_IN="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
# 第三方服务
STRIPE_PUBLISHABLE_KEY="encrypted:BOD5Fg+qI9dqhkh+gjCLrTFyhxEAhNDtLgwjkMZOr9l9CsvvhprwCrgsZbIRIFa1Vf6ATnWZ3/bacYnlBXlZ1Hc6YMZHog+ZuVW4AjwxCkB8I0AkcOeOsYzQx2fdtI4kFii01UIhN53jfmUjzLSPYw=="
STRIPE_SECRET_KEY="encrypted:BOD5Fg+qI9dqhkh+gjCLrTFyhxEAhNDtLgwjkMZOr9l9CsvvhprwCrgsZbIRIFa1Vf6ATnWZ3/bacYnlBXlZ1Hc6YMZHog+ZuVW4AjwxCkB8I0AkcOeOsYzQx2fdtI4kFii01UIhN53jfmUjzLSPYw=="
SENDGRID_API_KEY="encrypted:BCrnJ2sAZH2qwRlPvUqqWyEsd+cVeMQiOV5H/xZ7vjFfcMXHMunmAv/7+jUI356fkVtHfrXu+vBJLjXJiirgB2gky5vvy7h5jevgMS6BgPL5KwjC0tYPlYbe4Bfrf1funYqqrFYaPjsEO+77vCtVaBPz"
# 日志配置
LOG_LEVEL="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
LOG_FORMAT="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
# 功能开关
FEATURE_NEW_UI="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
FEATURE_ANALYTICS="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
.env.local (本地开发覆盖)
# 本地开发特定配置
DB_HOST=localhost
DB_NAME=myapp_local
DB_USER=localuser
DB_PASSWORD=localpass
# 本地调试
DEBUG=true
LOG_LEVEL=debug
# 本地服务端口
PORT=3001
# 禁用某些功能
FEATURE_ANALYTICS=false
FEATURE_EMAIL_NOTIFICATIONS=false
# 本地测试密钥
STRIPE_SECRET_KEY=sk_test_local_key
SENDGRID_API_KEY=SG.local_test_key
.env.test (测试环境)
# 测试环境配置
NODE_ENV=test
PORT=0
# 测试数据库
DB_HOST=localhost
DB_PORT=5433
DB_NAME=myapp_test
DB_USER=test_user
DB_PASSWORD=test_pass
# 测试 Redis
REDIS_HOST=localhost
REDIS_PORT=6380
# 测试 API
API_BASE_URL=http://localhost:3000/api
JWT_SECRET=test-secret-key
JWT_EXPIRES_IN=1h
# 禁用外部服务
STRIPE_SECRET_KEY=sk_test_fake
SENDGRID_API_KEY=SG.test_fake
EMAIL_ENABLED=false
# 测试日志
LOG_LEVEL=error
LOG_FORMAT=simple
# 测试功能开关
FEATURE_NEW_UI=true
FEATURE_ANALYTICS=false
.env.example (模板文件)
# 应用配置
NODE_ENV=development
PORT=3000
APP_NAME=MyApp
APP_VERSION=1.0.0
# 数据库配置
DB_HOST=localhost
DB_PORT=5432
DB_NAME=your_database_name
DB_USER=your_database_user
DB_PASSWORD=your_database_password
# Redis 配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
# API 配置
API_BASE_URL=http://localhost:3000/api
JWT_SECRET=your_jwt_secret_key
JWT_EXPIRES_IN=24h
# 第三方服务密钥
STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key
SENDGRID_API_KEY=SG.your_sendgrid_api_key
# 日志配置
LOG_LEVEL=info
LOG_FORMAT=combined
# 功能开关
FEATURE_NEW_UI=false
FEATURE_ANALYTICS=true
高级配置示例
变量扩展示例
# 基础配置
BASE_DOMAIN=example.com
PROTOCOL=https
PORT=443
# 扩展配置
API_URL=${PROTOCOL}://${BASE_DOMAIN}:${PORT}/api
WEB_URL=${PROTOCOL}://${BASE_DOMAIN}
WEBHOOK_URL=${API_URL}/webhooks
# 数据库连接字符串
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=admin
DB_PASS=secret123
DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}
# 默认值
CACHE_TTL=${CACHE_TTL:-3600}
MAX_CONNECTIONS=${MAX_CONNECTIONS:-100}
命令替换示例
# Git 信息
COMMIT_SHA=$(git rev-parse HEAD)
BRANCH_NAME=$(git branch --show-current)
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# 系统信息
HOSTNAME=$(hostname)
USER_NAME=$(whoami)
# 动态配置
CURRENT_VERSION=$(node -p "require('./package.json').version")
NODE_VERSION=$(node --version)
多服务配置示例
# 微服务配置
USER_SERVICE_URL=http://user-service:3001
ORDER_SERVICE_URL=http://order-service:3002
PAYMENT_SERVICE_URL=http://payment-service:3003
NOTIFICATION_SERVICE_URL=http://notification-service:3004
# 服务发现
CONSUL_HOST=consul
CONSUL_PORT=8500
SERVICE_REGISTRY_URL=http://${CONSUL_HOST}:${CONSUL_PORT}
# 负载均衡
NGINX_UPSTREAM_SERVERS=app1:3000,app2:3000,app3:3000
# 监控配置
PROMETHEUS_URL=http://prometheus:9090
GRAFANA_URL=http://grafana:3000
JAEGER_URL=http://jaeger:14268
部署脚本示例
package.json 脚本
{
"scripts": {
"dev": "dotenvx run -f .env.local -f .env -- npm run start:dev",
"start": "dotenvx run -- node dist/main.js",
"start:prod": "dotenvx run -f .env.production -- node dist/main.js",
"test": "dotenvx run -f .env.test -- jest",
"test:e2e": "dotenvx run -f .env.test -- jest --config ./test/jest-e2e.json",
"build": "dotenvx run -- npm run build:app",
"encrypt:prod": "dotenvx encrypt -f .env.production",
"validate:env": "dotenvx validate -f .env.production"
}
}
Docker Compose 示例
version: '3.8'
services:
app:
build: .
command: dotenvx run -f .env.production -- node app.js
environment:
- DOTENV_PRIVATE_KEY_PRODUCTION=${DOTENV_PRIVATE_KEY_PRODUCTION}
volumes:
- ./.env.production:/app/.env.production:ro
ports:
- "3000:3000"
depends_on:
- db
- redis
db:
image: postgres:15
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=secret123
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
command: redis-server --requirepass secret123
volumes:
postgres_data:
Kubernetes ConfigMap 示例
apiVersion: v1
kind: ConfigMap
metadata:
name: app-env-config
data:
.env.production: |
DOTENV_PUBLIC_KEY_PRODUCTION="026d4945b6513baec60f68b207f203ba534fb54d2b0c9952557d240815e42a7d83"
NODE_ENV="encrypted:BKzfW56VHobMDtfq+iU+MsjVlPDdiKYoJmKLMlUKzsds5dHWjY+GcKbUx7V54jX21kVa6kuBcINNmP/DwXZA2VSb6q8zhMU/Go59aQWqmoqip6jB8DTxc8GjxUF4lWO3PLWJqk8="
# ... 其他加密变量
---
apiVersion: v1
kind: Secret
metadata:
name: dotenv-private-key
type: Opaque
data:
DOTENV_PRIVATE_KEY_PRODUCTION: YmQ3YzUwYjM1MmNlMjM5NzNlYzlkYjM1NWQ3MDIxMjMwNWEwYmFhYWRlOTJmMDE2NWYwMjkxNWIyMTNiZmJlMg==
TOML 配置集成示例
基础 TOML 配置结合 dotenvx
config.toml (应用配置)
[app]
name = "MyApp"
version = "1.0.0"
debug = false
[server]
host = "0.0.0.0"
port = 3000
timeout = 30
[database]
driver = "postgres"
max_connections = 100
ssl_mode = "require"
[redis]
pool_size = 10
timeout = 5
[logging]
format = "json"
rotation = "daily"
[features]
new_ui = true
analytics = false
rate_limiting = true
.env (敏感配置)
# 数据库连接
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=admin
DB_PASSWORD=secret123
# Redis 连接
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=redis_secret
# API 密钥
JWT_SECRET=your_jwt_secret_key
STRIPE_SECRET_KEY=sk_test_your_stripe_key
SENDGRID_API_KEY=SG.your_sendgrid_key
# 外部服务
WEBHOOK_SECRET=webhook_secret_key
OAUTH_CLIENT_SECRET=oauth_client_secret
Node.js 集成示例
// config.js
const fs = require('fs')
const toml = require('toml')
require('@dotenvx/dotenvx').config()
// 读取 TOML 配置
const configFile = fs.readFileSync('./config.toml', 'utf8')
const config = toml.parse(configFile)
// 合并环境变量
const fullConfig = {
...config,
database: {
...config.database,
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
name: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
url: `postgres://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`
},
redis: {
...config.redis,
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD
},
auth: {
jwtSecret: process.env.JWT_SECRET,
jwtExpiresIn: '24h'
},
services: {
stripe: {
secretKey: process.env.STRIPE_SECRET_KEY
},
sendgrid: {
apiKey: process.env.SENDGRID_API_KEY
}
}
}
module.exports = fullConfig
Rust 项目集成示例
Cargo.toml
[package]
name = "myapp"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
toml = "0.8"
dotenv = "0.15"
config = "0.14"
config.toml
[app]
name = "MyRustApp"
version = "0.1.0"
workers = 4
[server]
host = "127.0.0.1"
port = 8080
keep_alive = 75
[database]
pool_size = 10
timeout = 30
ssl = true
[cache]
ttl = 3600
max_size = "100MB"
src/config.rs
use serde::{Deserialize, Serialize};
use std::env;
use std::fs;
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
pub app: AppConfig,
pub server: ServerConfig,
pub database: DatabaseConfig,
pub cache: CacheConfig,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct AppConfig {
pub name: String,
pub version: String,
pub workers: u32,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ServerConfig {
pub host: String,
pub port: u16,
pub keep_alive: u64,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct DatabaseConfig {
pub pool_size: u32,
pub timeout: u64,
pub ssl: bool,
pub url: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct CacheConfig {
pub ttl: u64,
pub max_size: String,
pub redis_url: String,
}
impl Config {
pub fn load() -> Result<Self, Box<dyn std::error::Error>> {
// 加载 dotenv
dotenv::dotenv().ok();
// 读取 TOML 配置
let config_str = fs::read_to_string("config.toml")?;
let mut config: Config = toml::from_str(&config_str)?;
// 从环境变量补充敏感信息
config.database.url = format!(
"postgres://{}:{}@{}:{}/{}",
env::var("DB_USER")?,
env::var("DB_PASSWORD")?,
env::var("DB_HOST")?,
env::var("DB_PORT")?,
env::var("DB_NAME")?
);
config.cache.redis_url = format!(
"redis://:{}@{}:{}",
env::var("REDIS_PASSWORD").unwrap_or_default(),
env::var("REDIS_HOST")?,
env::var("REDIS_PORT")?
);
Ok(config)
}
}
Python 项目集成示例
pyproject.toml
[tool.poetry]
name = "myapp"
version = "0.1.0"
description = "My Python App"
[tool.poetry.dependencies]
python = "^3.9"
fastapi = "^0.104.0"
uvicorn = "^0.24.0"
python-dotenv = "^1.0.0"
toml = "^0.10.2"
pydantic = "^2.5.0"
sqlalchemy = "^2.0.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.app]
name = "MyPythonApp"
version = "0.1.0"
debug = false
[tool.app.server]
host = "0.0.0.0"
port = 8000
workers = 4
[tool.app.database]
pool_size = 20
echo = false
pool_timeout = 30
[tool.app.cache]
default_timeout = 300
key_prefix = "myapp:"
config.py
import os
import toml
from pathlib import Path
from pydantic import BaseSettings
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
class Settings(BaseSettings):
# 从 TOML 加载基础配置
def __init__(self):
super().__init__()
self._load_toml_config()
def _load_toml_config(self):
config_path = Path("pyproject.toml")
if config_path.exists():
with open(config_path, 'r') as f:
toml_config = toml.load(f)
app_config = toml_config.get('tool', {}).get('app', {})
# 合并 TOML 配置
self.app_name = app_config.get('name', 'MyApp')
self.app_version = app_config.get('version', '0.1.0')
self.debug = app_config.get('debug', False)
server_config = app_config.get('server', {})
self.host = server_config.get('host', '0.0.0.0')
self.port = server_config.get('port', 8000)
self.workers = server_config.get('workers', 4)
# 敏感配置从环境变量获取
database_url: str = os.getenv('DATABASE_URL', '')
redis_url: str = os.getenv('REDIS_URL', '')
secret_key: str = os.getenv('SECRET_KEY', '')
# API 密钥
stripe_secret_key: str = os.getenv('STRIPE_SECRET_KEY', '')
sendgrid_api_key: str = os.getenv('SENDGRID_API_KEY', '')
class Config:
env_file = '.env'
case_sensitive = True
settings = Settings()
Go 项目集成示例
config.toml
[app]
name = "MyGoApp"
version = "1.0.0"
environment = "development"
[server]
host = "localhost"
port = 8080
read_timeout = "30s"
write_timeout = "30s"
idle_timeout = "60s"
[database]
max_open_conns = 25
max_idle_conns = 5
conn_max_lifetime = "5m"
[cache]
default_expiration = "10m"
cleanup_interval = "15m"
config.go
package config
import (
"fmt"
"os"
"time"
"github.com/BurntSushi/toml"
"github.com/joho/godotenv"
)
type Config struct {
App AppConfig `toml:"app"`
Server ServerConfig `toml:"server"`
Database DatabaseConfig `toml:"database"`
Cache CacheConfig `toml:"cache"`
// 敏感信息从环境变量获取
DatabaseURL string
RedisURL string
JWTSecret string
StripeKey string
SendGridKey string
}
type AppConfig struct {
Name string `toml:"name"`
Version string `toml:"version"`
Environment string `toml:"environment"`
}
type ServerConfig struct {
Host string `toml:"host"`
Port int `toml:"port"`
ReadTimeout time.Duration `toml:"read_timeout"`
WriteTimeout time.Duration `toml:"write_timeout"`
IdleTimeout time.Duration `toml:"idle_timeout"`
}
type DatabaseConfig struct {
MaxOpenConns int `toml:"max_open_conns"`
MaxIdleConns int `toml:"max_idle_conns"`
ConnMaxLifetime time.Duration `toml:"conn_max_lifetime"`
}
type CacheConfig struct {
DefaultExpiration time.Duration `toml:"default_expiration"`
CleanupInterval time.Duration `toml:"cleanup_interval"`
}
func Load() (*Config, error) {
// 加载 .env 文件
if err := godotenv.Load(); err != nil {
// .env 文件不存在时不报错
fmt.Println("Warning: .env file not found")
}
var config Config
// 读取 TOML 配置
if _, err := toml.DecodeFile("config.toml", &config); err != nil {
return nil, fmt.Errorf("failed to decode config.toml: %w", err)
}
// 从环境变量获取敏感信息
config.DatabaseURL = fmt.Sprintf(
"postgres://%s:%s@%s:%s/%s?sslmode=require",
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_HOST"),
os.Getenv("DB_PORT"),
os.Getenv("DB_NAME"),
)
config.RedisURL = fmt.Sprintf(
"redis://:%s@%s:%s",
os.Getenv("REDIS_PASSWORD"),
os.Getenv("REDIS_HOST"),
os.Getenv("REDIS_PORT"),
)
config.JWTSecret = os.Getenv("JWT_SECRET")
config.StripeKey = os.Getenv("STRIPE_SECRET_KEY")
config.SendGridKey = os.Getenv("SENDGRID_API_KEY")
return &config, nil
}
Docker 多阶段构建示例
Dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 复制配置文件
COPY config.toml ./
COPY .env.production ./
# 安装 dotenvx
RUN npm install -g @dotenvx/dotenvx
# 运行阶段
FROM node:18-alpine AS runner
WORKDIR /app
# 复制依赖和配置
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/config.toml ./
COPY --from=builder /app/.env.production ./
COPY --from=builder /usr/local/bin/dotenvx /usr/local/bin/
# 复制应用代码
COPY . .
# 使用 dotenvx 运行应用
CMD ["dotenvx", "run", "-f", ".env.production", "--", "node", "app.js"]
最佳实践总结
1. 配置分离原则
config.toml -> 非敏感的应用配置
.env -> 敏感信息(密码、密钥等)
.env.example -> 环境变量模板
2. 环境特定配置
config.toml -> 基础配置
config.dev.toml -> 开发环境覆盖
config.prod.toml -> 生产环境覆盖
.env.development -> 开发环境敏感信息
.env.production -> 生产环境敏感信息(加密)
3. 配置验证
// config-validator.js
const Joi = require('joi')
const configSchema = Joi.object({
database: Joi.object({
url: Joi.string().uri().required(),
pool_size: Joi.number().min(1).max(100).required()
}).required(),
redis: Joi.object({
url: Joi.string().uri().required(),
timeout: Joi.number().min(1).required()
}).required(),
auth: Joi.object({
jwtSecret: Joi.string().min(32).required()
}).required()
})
function validateConfig(config) {
const { error, value } = configSchema.validate(config)
if (error) {
throw new Error(`Configuration validation failed: ${error.message}`)
}
return value
}
module.exports = { validateConfig }
这些配置示例展示了 dotenvx 在不同环境和场景下的实际应用,特别是与 TOML 配置文件的结合使用,帮助开发者快速上手并在项目中正确使用 dotenvx。