环境变量管理需分清三种来源优先级:dockerfile env(最低)、env_file(中等)、environment字段(高)、--env-file或shell export(最高);敏感信息禁明文落盘,须用密钥管理服务;多环境应分层隔离,运行时须校验关键变量。
环境变量是 docker 应用配置的核心纽带,但用错方式极易导致凭据泄露、配置混乱甚至生产事故。关键不在于“能不能用”,而在于“怎么用才安全可控”。下面从落地场景出发,讲清楚怎么管、怎么防、怎么切换。
环境变量的三种来源与优先级必须理清
同一变量名可能来自多个地方,Docker Compose 会按固定顺序覆盖——理解这个顺序,才能避免“改了没生效”或“被意外覆盖”:
-
最低优先级:Dockerfile 中的
ENV指令(构建时固化,难以动态调整) -
中等优先级:通过
env_file加载的文件(如.env.production),适合集中管理多环境配置 -
高优先级:
docker-compose.yml中environment字段直接定义(适合少量调试变量或强制覆盖) -
最高优先级:启动命令中用
docker-compose --env-file显式指定,或宿主机 shell 已export的变量(CI/CD 流水线常用)
敏感信息绝不能明文落盘
数据库密码、API 密钥、JWT 秘钥等,一旦写进 .env 文件并误提交到 Git,就等于把钥匙贴在门上。真正安全的做法是:
- 所有含敏感字段的
.env文件必须加入.gitignore,且 CI/CD 环境中禁止读取本地文件 - 生产环境统一走密钥管理服务:HashiCorp Vault、AWS Secrets Manager 或 Kubernetes Secret,容器启动时动态拉取解密
- 若短期需本地测试,可用
docker-compose --env-file临时加载,但该文件不纳入版本控制,且权限设为600(仅属主可读写) - 在应用代码中禁用日志打印敏感变量,例如 PHP 的
$_ENV['DB_PASSWORD']不应出现在error_log()中
多环境配置要分层隔离,不能靠“改一个文件切环境”
开发、预发、生产共用一套 .env?这是典型隐患。推荐按职责拆分:
-
.env.common:存放通用非敏感项,如APP_NAME、TIMEZONE -
.env.development:本地调试专用,可含LOG_LEVEL=debug、DB_HOST=localhost -
.env.production:仅含生产必需项,且只通过安全通道注入(如 Vault 注入脚本) - Compose 文件中用
env_file同时加载多个文件:env_file: [".env.common", ".env.${ENV_TYPE}"],再通过ENV_TYPE=production docker-compose up控制加载路径
运行时验证比“写了就算”更重要
变量缺失或格式错误常导致容器启动即退出,但错误信息模糊。应在应用入口加轻量检查:
- Shell 启动脚本中判断关键变量是否存在:
[ -z "$DB_PASSWORD" ] && echo "FATAL: DB_PASSWORD missing" >&2 && exit 1 - 在 Node.js 中用
process.env.DB_PASSWORD || fail("missing DB_PASSWORD") - 对敏感变量做基础校验(如长度、是否含空格),避免因拼写错误注入空字符串引发越权连接
不复杂但容易忽略:环境变量不是配置终点,而是可信链的起点。从加载方式、存储位置、作用范围到运行时行为,每一步都得有约束。











