![我可以在 nginx 提供的静态文件中使用 nginx 环境变量吗?](https://linux22.com/image/654401/%E6%88%91%E5%8F%AF%E4%BB%A5%E5%9C%A8%20nginx%20%E6%8F%90%E4%BE%9B%E7%9A%84%E9%9D%99%E6%80%81%E6%96%87%E4%BB%B6%E4%B8%AD%E4%BD%BF%E7%94%A8%20nginx%20%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E5%90%97%EF%BC%9F.png)
如果我在 nginx 配置中使用环境变量,并且 nginx 配置为仅提供静态文件(html、js、css - 例如 AngularJs 应用程序),是否有任何方法可以在 nginx 提供的 JS 文件中使用环境变量?或者唯一的方法是运行非静态服务器,例如 io.js、php 等。
顺便说一句,您不能在 nginx 的配置中本机使用环境变量。
当我谈论 nginx 配置中的环境变量时,我的意思是像这篇文章中那样:如何在 Nginx.conf 中使用环境变量他们使用env APP_WEB_1_PORT_5000_TCP_ADDR;
和$ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"};
准确解释您的用例
我的具体用例是,我在 Docker 容器中有一个由 nginx 驱动的 AngularJS 应用程序。该应用程序是一个“单页应用程序”,它使用在另一个系统上运行的 API。目前,我在生产和暂存之间运行不同的 Docker 容器,因为该应用程序有一些不同的配置,例如 Google-Analtyics 代码。此环境特定数据保存在一个config.js
文件中,并且值当前是硬编码的,master
git 中的分支有一个值,分支有不同的值staging
。我想更改设计,以便我可以使用相同容器既可用于生产环境,也可用于暂存环境。我想在运行容器时将 ENV 变量传递到容器中(docker run -e GACODE=UA-12345-6 ...
)并让 nginx 使用 ENV 变量(通过env GACODE;
,$ENV{"GACODE"}
这样config.js
文件就可以使用传入的 GoogleAnaltyics 代码,而不是对它们进行硬编码)。我不知道这是否可行(因此提出问题 ;))。仅使用 nginx 会使我的容器成为单进程,而如果我必须使用 io.js,那么我将需要多个链接容器,并且更多移动部件会更加复杂)。
答案1
我一直在研究如何解决与 OP 相同的问题,并且这篇文章出现在 Google 搜索中,所以我想添加一个潜在的解决方案。
这篇文章概述了如何在 nginx 配置中公开环境变量:https://blog.doismellburning.co.uk/environment-variables-in-nginx-config/
并且您可以返回文件系统中没有文件的内容:从 Nginx 配置回复 200,但不提供文件
将这两件事放在一起,我们得到以下结果:
env MY_ENV_VAR;
# Snip
http {
# Snip
server {
# Snip
location ~ ^/config.js$ {
add_header Content-Type text/javascript;
set_by_lua $env_var 'return os.getenv("MY_ENV_VAR")';
return 200 'const MY_ENV_VAR = \'$env_var\'';
}
}
}
这在测试环境中对我来说很有效。这有点麻烦(不确定这是否比在 Docker 启动时自动生成包含所需变量的文件更好)。
希望有所帮助。
答案2
我尝试使用子过滤器和 nginx 环境变量,但得出的结论是这是不可能的。
例如,这显示了我的实验,并显示了使用传递给 nginx 的 ENV不是server
在一个区块内工作:
env TOMTEST1; # OK - makes $ENV{"TOMTEST1"} available but NOT in server block.
http {
server {
# set $TOMTEST1 $ENV{"TOMTEST1"}; # KO - DOES NOT WORK - NGINX WONT START
set $TOMTEST2 'tomtest2 Var'; # OK - THIS DOES WORK OK
sub_filter 'TOM_TEST2' $TOMTEST2; # OK - but not useful to me.
sub_filter 'TOM_TEST3' 'tomtest3 Var'; # OK - but not useful to me.
sub_filter_once off; # Don't stop at the first match, replace all of them
sub_filter_types "text/javascript" "application/json"; # Apply to these mime types in addition to text/html
# Serve static files
location / {
try_files $uri /index.html =404;
}
...
我提供的静态 config.json 文件包含各种测试字符串,如下所示:
{
"environment": "local",
"test1": "$ENV{"TOMTEST1"}",
"test3": "TOM_TEST2",
"test4": "TOM_TEST3",
}
正如@AD7six提到的,解决方法是让一个脚本在 nginx 启动之前运行,以便从占位符生成有效的配置文件。但这引出了一个问题,如果一个脚本要在 nginx 启动之前运行,我不妨在该脚本中设置我的文件的内容,而根本不用config.json
管它。sub_filter
答案3
子过滤器
如果你想要一个简单的字符串替换,你可以使用子过滤器。 例如:
server {
sub_filter "REPLACE_THIS" "with this";
sub_filter_once off; # Don't stop at the first match, replace all of them
sub_filter_types "text/javascript" "application/json"; # Apply to these mime types in addition to text/html
# Everything else
}
然而无法读取环境变量在nginx 配置 - 您当然可以按照您需要/想要的任何方式编写 nginx 配置文件脚本来生成有效的配置文件,然后重新加载 nginx。