我可以在 nginx 提供的静态文件中使用 nginx 环境变量吗?

我可以在 nginx 提供的静态文件中使用 nginx 环境变量吗?

如果我在 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文件中,并且值当前是硬编码的,mastergit 中的分支有一个值,分支有不同的值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。

相关内容