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

Tom*_*Tom 13 nginx environment-variables static-content docker

如果我在 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 那么我将需要多个链接的容器,并且更多的移动部件更复杂)。

小智 7

我一直在寻找解决与 OP 相同的问题,这篇文章出现在 Google 搜索中,所以我想我会添加一个潜在的解决方案。

这篇文章概述了如何在 nginx 配置中公开环境变量:https : //blog.doismellburning.co.uk/environment-variables-in-nginx-config/

并且您可以在文件系统中没有文件的情况下返回内容:Reply with 200 from Nginx config without service a file

将这两件事放在一起,我们最终得到以下结果:

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\'';
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这在测试环境中对我有用。这有点麻烦(不确定它是否比在 Docker 启动时自动生成包含您需要的变量的文件更好)。

希望有帮助。


Tom*_*Tom 5

我尝试使用sub_filter和 nginx 环境变量,但得出的结论是这是不可能的

例如,这说明我的实验和使用ENVS节目传递给nginx的就不是一个内工作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;
        }
        ...
Run Code Online (Sandbox Code Playgroud)

我提供的静态 config.json 文件有各种测试字符串,如下所示:

{
    "environment": "local",
    "test1": "$ENV{"TOMTEST1"}",
    "test3": "TOM_TEST2",
    "test4": "TOM_TEST3",
}
Run Code Online (Sandbox Code Playgroud)

正如@AD7six 所提到的,继续的方法是在 nginx 开始从占位符生成有效的配置文件之前运行一个脚本。但这引出了一个问题,如果脚本要在 nginx 启动之前运行,我不妨config.json在该脚本中设置我的文件的内容,而根本不用理会sub_filter

  • 如果是针对一个静态文件 - 不通过 nginx 配置进行操作当然是有意义的,我认为您的用例比这更广泛。对于信息/对比,我在开发设置中使用 `sub_filter "example.com" "example.dev";` 将生产域的任何和所有引用替换为本地环境,因为这些引用来自 3rd 方 api 响应/应用程序代码/js/db 转储/等。- 即对于 nginx,它可以位于任何 html/js/json 响应中的任何位置。+1 (2认同)

AD7*_*six 4

子过滤器

如果您想要简单的字符串替换,可以使用sub_filter。例如:

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
}
Run Code Online (Sandbox Code Playgroud)

但是,不可能读取nginx 配置中的环境变量- 您当然可以以任何您需要/想要生成有效配置文件的方式编写编写 nginx 配置文件的脚本,然后重新加载 nginx。