Nginx容器中需分三步实现环境变量透传:先通过docker/k8s注入变量至进程空间,再在nginx.conf main上下文用env指令声明,最后用$ENV{VAR}在日志或响应头中引用;复杂场景(如proxy_pass)须借助OpenResty的set_by_lua_block动态生成。

在容器化部署中,Nginx 本身不能直接用 $VAR 引用系统环境变量——env 指令只控制 worker 进程是否继承变量,不提供配置层的变量插值能力。真正“透传并使用”需分两步:先让变量进进程空间,再通过支持机制读取并注入配置。以下是贴近生产环境的实战路径。
第一步:确保环境变量进入 Nginx 进程
在容器启动时,环境变量必须真实存在于 Nginx 主进程环境中,否则后续一切无效。常见方式有:
-
Docker run 启动:用
-e显式传入,例如:docker run -e APP_ENV=staging -e API_HOST=https://api.example.com nginx:alpine -
Docker Compose:在
services.nginx.environment下声明,或挂载.env文件 -
Kubernetes Pod:通过
env:或envFrom:注入到容器,如valueFrom.fieldRef.fieldPath: metadata.name可透传 Pod 名称
验证是否生效:进入容器执行 ps auxf | grep nginx 查主进程 PID,再运行 cat /proc/<pid>/environ | tr '\0' '\n' | grep APP_ENV</pid>,能看到输出即表示已注入。
第二步:在 nginx.conf 中声明并引用(Nginx ≥ 1.19)
Nginx 1.19.0 起原生支持 $ENV{VAR_NAME} 语法,但前提是该变量已在进程环境里,且已在主配置顶层用 env 显式声明。
在 /etc/nginx/nginx.conf 的最外层(main 上下文,即 events 块之前)添加:
env APP_ENV; env API_HOST;
然后在 http 或 server 块中即可安全使用:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'env=$ENV{APP_ENV} api=$ENV{API_HOST}';
<p>server {
listen 80;
location /health {
add_header X-App-Env $ENV{APP_ENV};
add_header X-Api-Host $ENV{API_HOST};
return 200 "OK (env: $ENV{APP_ENV})\n";
}
}⚠️ 注意:$ENV{} 不能用于指令参数直用位置(如 root /var/www/$ENV{APP_ENV}),仅适用于日志、响应头、add_header 等支持运行时变量的上下文。
第三步:动态代理等复杂场景用 Lua 补足(推荐 OpenResty)
若需将环境变量用于 proxy_pass、root 或条件路由,必须借助运行时模块。OpenResty 是最轻量可靠的选择:
- 在
http块顶部定义变量:
set_by_lua_block $backend_url {
local host = os.getenv("API_HOST") or "http://localhost:8000"
return host
}
set_by_lua_block $static_root {
local env = os.getenv("APP_ENV") or "prod"
return "/usr/share/nginx/html/" .. env
}- 在
location中使用:
location /api/ {
proxy_pass $backend_url;
proxy_set_header X-Deploy-Env $ENV{APP_ENV};
}
<p>location /assets/ {
alias $static_root;
}此方式支持任意逻辑判断与拼接,适合 CI/CD 动态部署、多环境灰度等场景。
避坑提醒:哪些写法一定失败
以下看似合理,实则无效或报错,请避免:
-
env APP_ENV;写在http或server块内 → 报错"env" directive is not allowed here -
root /var/www/$APP_ENV;→ Nginx 将$APP_ENV当作字面字符串,不会展开,且可能触发invalid number of arguments - 只设
Environment=APP_ENV=dev在 systemd,但 nginx.conf 里没写env APP_ENV;→ worker 进程无法访问该变量 - 在 Dockerfile 用
ENV APP_ENV=dev,但运行时未覆盖 → 变量固化,失去“动态透传”意义
核心原则:环境变量是操作系统层面的概念,Nginx 配置是静态文本解析器;二者之间没有自动桥接,必须显式声明 + 显式引用,或靠外部工具/模块介入。


















