环境变量注入失败需按加载顺序排查:environment字段>宿主机shell变量>.env文件>env_file文件;同名变量逐级覆盖;缺失时无fallback;注意语法错误、类型转换、敏感信息泄露及安全注入闭环控制。
环境变量注入失败或行为异常,是 docker 应用部署中最隐蔽也最常被低估的问题之一。它不一定会立刻报错,却可能让应用静默降级、连接失败、配置错乱,甚至引发安全泄露。排查关键不在“有没有设”,而在“谁设的、怎么传的、在哪读的、是否被覆盖”。
环境变量没生效?先看加载顺序和覆盖逻辑
Docker Compose 对环境变量有明确优先级:容器内 environment 字段 > 宿主机 shell 变量 > .env 文件 > env_file 指定的文件。同名变量会逐级覆盖。
- 如果 docker-compose.yml 里写了
- APP_ENV=${APP_ENV},但 .env 文件中没定义 APP_ENV,该变量值为空,不会 fallback 到宿主机的同名变量 - 若在启动前执行了
export DB_PASS=abc,又在 docker-compose.yml 中显式写了- DB_PASS=xyz,最终容器内取到的是 xyz - 检查是否误用了
${VAR:-default}语法但拼写错误(如少写冒号),导致变量未展开
容器启动就退出?重点查变量缺失与类型错误
PHP、Node.js 等应用常在启动阶段校验必要变量,缺失即 panic。典型日志如:Error: Environment variable 'DB_HOST' is missing 或 FATAL: invalid port number ''。
- 用
docker-compose config预览实际解析后的配置,确认变量已正确展开 - 启动后立即执行
docker-compose exec php printenv | grep -i db,验证变量是否真实注入容器环境 - 注意类型隐式转换问题:比如
DEBUG=true在 PHP 中用filter_var($_ENV['DEBUG'], FILTER_VALIDATE_BOOLEAN)才能转为布尔值,直接比较字符串容易出错
敏感信息泄露风险:别让密码出现在日志或进程列表里
环境变量一旦被打印、记录或暴露在调试接口中,等同于明文分发凭证。
- 禁止在启动脚本、Dockerfile 的 RUN 指令或应用日志中 echo/printenv 敏感变量(如 DB_PASS、API_KEY)
- 避免使用
ps aux | grep php查看进程时泄露命令行参数——改用docker inspect --format='{{.Config.Env}}' <container></container>安全查看 - 生产环境禁用调试模式(如
XDEBUG_MODE=debug)、关闭错误页面详细信息(display_errors=Off),防止 $_ENV 被意外输出
安全注入的落地建议:从开发到上线的闭环控制
不是“加个 -e 就算注入”,而是要确保变量来源可信、传递可控、使用可审计。
- 本地开发用
.env+env_file,但必须把 .env 加入.gitignore,且 CI/CD 流水线禁止读取该文件 - 生产环境禁用
environment:明文写法,改用secrets:(Swarm)或envFrom:+Secret(K8s);Docker Desktop 用户可用docker secret create配合挂载 - PHP 应用中统一通过
getenv()或$_ENV读取,避免混用$_SERVER(部分变量需variables_order配置支持) - 定期扫描镜像:用
trivy image --severity CRITICAL your-php-app:latest检测硬编码密钥或敏感路径











