Nginx 配置中如何使用环境变量?

Nginx 原生不支持在配置里展开环境变量;可用方案:env 指令+set、envsubst 启动时模板渲染、Docker 官方镜像的 .template 机制、Lua/perl 模块,附示例与 FAQ。

最佳实践
Nginx 配置中如何使用环境变量?封面

坏消息:Nginx 配置本身不做环境变量插值——listen $PORT; 这种写法不会被展开。 好消息:有几条成熟的绕行路线,容器场景最常用的是 envsubst 模板渲染(官方 Nginx 镜像已内置)。

方案一:envsubst 启动时渲染(容器推荐)

官方 nginx Docker 镜像会把 /etc/nginx/templates/*.template 用环境变量渲染到 /etc/nginx/conf.d/

模板文件 default.conf.template

server {
    listen ${PORT:-80};
    server_name ${SERVER_NAME};

    location / {
        proxy_pass ${UPSTREAM_URL};
    }
}

运行容器:

docker run -e PORT=8080 -e SERVER_NAME=example.com \
  -e UPSTREAM_URL=http://backend:9000 nginx

启动时 ${PORT} 等会被替换成实际值。自建镜像也可用同样思路:entrypoint 里 envsubst '$PORT $SERVER_NAME' < tmpl > conf 再启动 Nginx。

方案二:env 指令(能力有限,先了解边界)

env MY_VAR;          # 主上下文声明:允许 worker 继承该变量

env 只是把变量带进 worker 进程的环境不能在配置里当值用。它配合能读环境的模块(如 Lua 的 os.getenv、Perl 模块、或 auth_request 的某些场景)才有意义。想在 listenproxy_pass 这类指令里直接用?不行。

方案三:Lua / Perl 动态读取

装了 ngx_http_lua_module(OpenResty 自带):

env UPSTREAM_URL;

server {
    location / {
        access_by_lua_block {
            ngx.var.upstream = os.getenv("UPSTREAM_URL")
        }
        proxy_pass $upstream;
    }
}

灵活但引入了 Lua 依赖,多数场景方案一已够。

方案四:配置生成工具

Ansible/Jinja2、Consul Template、confd 等——本质上和 envsubst 一样,都是"先渲染再启动"。适合配置复杂、来源多样的环境。

观测云对照

模板渲染让"一份镜像、多套环境"成为可能,代价是渲染错误只在启动时暴露。把 Nginx 的启动日志和 error.log 接入观测云,配合对容器重启事件的监控告警,配置渲染失败导致的反复重启能在第一分钟被发现;访问日志统一采集后,不同环境的流量对照也不再需要逐台登机器。

常见问题(FAQ)

Q:为什么 $HOSTNAME 在 nginx.conf 里没被替换?
A:Nginx 解析配置时不读环境变量,$xxx 在 Nginx 里是内置变量语法(如 $host),和 shell 环境变量完全是两回事。要环境插值必须启动前渲染。

Q:envsubst 会把 Nginx 自己的 $uri 之类也吃掉吗?
A:会!envsubst 默认替换所有 $VAR。解决:只替换指定变量——envsubst '$PORT $UPSTREAM_URL' < in > out,Nginx 内置变量不动。

Q:运行时改了环境变量,Nginx 会跟着变吗?
A:不会。配置是启动时读取的,改完必须重渲染并 reload/restart。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台