随记
.env 文件:以环境变量承载运行配置
介绍 .env 的通用键值写法、字符串转换与覆盖关系,说明不同工具方言及秘密管理注意事项。
发布于 2026年7月24日
.env 文件:以环境变量承载运行配置
.env 文件通常由工具读取,再把其中的键值加载为进程环境变量。它适合保存随部署变化的少量参数,例如监听端口、调试开关和外部服务地址,尤其常见于本地开发、容器启动和十二要素应用。
.env 不是统一标准。引号、行尾注释、多行值、变量插值、转义和覆盖顺序都可能因 dotenv 库、Shell、Docker Compose 或框架而不同。跨工具复制之前,应以目标工具文档和实际解析结果为准。
一、完整示例
APP_NAME=config-demo
APP_DEBUG=false
APP_FEATURES=search,cache
SERVER_HOST=127.0.0.1
SERVER_PORT=8080
DATABASE_POOL_SIZE=10
层级通过大写名称和下划线压平。false、8080、10 和 search,cache 通常都会作为字符串进入环境,应用需要自行转换为布尔值、整数和列表。
二、常用语法
最常见的可移植写法是一行一个 KEY=value:
SERVER_PORT=8080
LOG_LEVEL=info
EMPTY_VALUE=
键通常使用大写字母、数字和下划线,并避免空格。# 常用于整行注释:
# 本地开发使用的监听地址
SERVER_HOST=127.0.0.1
包含空格、# 或特殊字符的值最好加引号,但单引号、双引号和反斜杠的具体解释仍由工具决定:
WELCOME_MESSAGE="hello config demo"
COLOR_CODE="#67e8f9"
不要默认 ${OTHER_VAR} 一定会展开,也不要默认 export KEY=value、多行字符串或命令替换一定受支持。若需要这些能力,应明确绑定某个实现,并为其写兼容测试。
三、覆盖关系
.env 文件只是配置来源之一。操作系统环境、命令行参数、框架专用文件和多个 .env.* 文件之间谁覆盖谁,没有通用答案。
例如某些工具让已经存在的进程环境变量优先,另一些工具允许通过选项覆盖;Docker Compose 的项目 .env、服务 env_file、Shell 环境和命令行 -e 也属于不同用途。项目文档应写出完整的加载顺序,而不是只写“支持 .env”。
四、适用场景
.env 适合:
- 本地开发时为应用准备少量环境变量。
- 容器或进程启动前注入按部署变化的参数。
- 为 CI 提供无秘密的变量名模板。
- 在不同语言之间共享扁平字符串设置。
- 配置最终本来就要进入进程环境。
复杂对象、较长列表和大量说明文字不适合 .env。这类内容应放在 TOML、YAML、JSON 等结构化文件中,再用环境变量覆盖少数部署相关字段。
五、与其他格式对比
| 对比格式 | .env 的优势 |
.env 的不足 |
|---|---|---|
| INI | 直接对应进程环境,部署覆盖方便 | 没有 section,方言差异同样明显 |
| TOML | 简单、跨语言、容易由平台注入 | 没有原生类型、数组和层级 |
| YAML | 扁平参数不受缩进影响 | 无法自然表达复杂声明式配置 |
| Properties | 不局限于 Java 生态,适合启动环境 | Properties 的转义和 Java API 行为更明确 |
环境变量也有大小限制、可见性和平台差异。不要把 .env 当作适用于所有配置的万能格式。
六、常见错误与安全提醒
- 不要提交含真实秘密的
.env。将其加入忽略规则,只提交不带值或使用安全示例值的.env.example。 - 秘密泄漏后要轮换。从最新提交删除文件并不能自动清除 Git 历史、构建缓存和已复制的令牌。
- 所有值按字符串处理。显式解析布尔值,避免把非空字符串
"false"直接当作真。 - 记录覆盖顺序。特别是
.env、.env.local、CI 变量和运行环境同时存在时。 - 不要依赖隐式插值和命令替换。不同实现的行为和安全边界差异很大。
- 限制文件权限与传播范围。不要把
.env打进公开镜像、客户端资源、日志或错误页面。 - 生产环境优先使用平台秘密管理能力,并保持应用只读取所需变量。
七、选型建议
把 .env 用作“环境变量的本地载体”,而不是完整配置语言。适合它的是少量、扁平、随部署变化的字符串参数;复杂且稳定的应用结构应保留在可校验的配置文件中。
为了兼容不同工具,应尽量采用简单的 KEY=value、整行 # 注释和必要的引号,并明确目标解析器。任何超出这个交集的语法都要在项目文档中标记。