Posso usar variáveis ​​de ambiente nginx em arquivos estáticos que o nginx serve?

10

Se eu usar uma variável de ambiente na configuração do nginx, e o nginx estiver configurado para servir apenas arquivos estáticos (html, js, css - por exemplo, um aplicativo AngularJs), existe alguma maneira de usar a variável de ambiente em um arquivo JS que o nginx serve ? Ou é a única maneira de fazer isso para executar um servidor não estático, por exemplo, io.js, php, etc.


Aliás, você não pode usar variáveis ​​de ambiente nativamente na configuração do nginx.

Quando falo sobre os ambientes de variáveis ​​na configuração do nginx, quero dizer como neste post: Como posso usar variáveis ​​de ambiente no Nginx.conf, onde eles usam env APP_WEB_1_PORT_5000_TCP_ADDR;e$ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"};


Explique exatamente seu caso de uso

Meu caso de uso específico é que eu tenho um aplicativo AngularJS alimentado por nginx em um contêiner de docker. O aplicativo é um "Aplicativo de página única" que consome uma API em execução em outro sistema completamente. Atualmente, eu executo um contêiner de docker diferente entre produção e armazenamento temporário, porque o aplicativo tem algumas configurações diferentes, por exemplo, o código do Google-Analtyics. Esses dados específicos do ambiente são mantidos em um config.jsarquivo e os valores atualmente são codificados, um valor para a masterramificação no git e um valor diferente para a stagingramificação. Quero alterar o design para poder usar o mesmo contêiner para produção e preparação. Quero passar uma ENV var para o contêiner quando executá-la ( docker run -e GACODE=UA-12345-6 ...) e o nginx usa a ENV var (via env GACODE;e $ENV{"GACODE"}assim oconfig.jsO arquivo pode usar os códigos do GoogleAnaltyics que são passados, em vez de codificá-los). Não sei se isso é possível ou não (daí a questão;)). Usar apenas o nginx torna meu contêiner um processo único, enquanto que, se eu precisar usar o io.js., precisarei de vários contêineres vinculados e mais partes móveis serão mais complexas).

Tom
fonte
O que ?! Explique exatamente o seu caso de uso, pois parece que você está olhando do lado errado. Aliás, você não pode usar variáveis ​​de ambiente nativamente na configuração do nginx.
Xavier Lucas
Obrigado @XavierLucas - atualizei a pergunta para tentar explicar mais.
19415 Tom

Respostas:

4

sub_filter

Se você deseja uma substituição simples de cadeia, use sub_filter . Por exemplo:

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
}

Entretanto , não é possível ler uma variável de ambiente no nginx config - você pode, naturalmente, escrever o arquivo de configuração nginx da maneira que precisar / desejar produzir um arquivo de configuração válido e recarregar o nginx.

AD7six
fonte
4

Eu experimentei usar variáveis ​​de ambiente sub_filter e nginx, mas concluí que não é possível .

Por exemplo, isso mostra minhas experiências e mostra que o uso de ENVs passados ​​para o nginx não funciona em um serverbloco:

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;
        }
        ...

onde o arquivo estático config.json que estou servindo possui várias cadeias de teste como as seguintes:

{
    "environment": "local",
    "test1": "$ENV{"TOMTEST1"}",
    "test3": "TOM_TEST2",
    "test4": "TOM_TEST3",
}

Como o @ AD7six mencionado, o caminho a seguir é ter um script que seja executado antes do nginx começar a produzir um arquivo de configuração válido a partir de espaços reservados. Mas isso levanta a questão: se um script for executado antes do nginx iniciar, é melhor definir o conteúdo do meu config.jsonarquivo nesse script e não me incomodar sub_filter.

Tom
fonte
2
Se for para um arquivo estático - certamente faz sentido não fazê-lo através da configuração do nginx, presumi que o seu caso de usuário era um pouco mais amplo que isso. Para informações / contraste, eu uso sub_filter "example.com" "example.dev";em uma configuração de desenvolvimento para substituir toda e qualquer referência ao domínio de produção no ambiente local, porque essas referências são provenientes de respostas de API de terceiros / código do aplicativo / js / db dumps / etc. - ou seja, para o nginx, pode estar em qualquer lugar em qualquer resposta html / js / json. +1
AD7six 26/03/2015
3

Eu estive procurando resolver o mesmo problema que o OP e esta postagem surgiu na pesquisa do Google, então pensei em adicionar uma solução em potencial.

Esta publicação descreve como você pode expor uma variável de ambiente na configuração do nginx: https://blog.doismellburning.co.uk/environment-variables-in-nginx-config/

E você pode retornar conteúdo sem ter um arquivo no sistema de arquivos: responda com 200 da configuração do Nginx sem exibir um arquivo

Juntando essas duas coisas, terminamos com o seguinte:

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\'';
        }
    }
}

Isso funcionou para mim em um ambiente de teste. É um pouco complicado (não é certo que seja melhor do que gerar automaticamente um arquivo na inicialização do Docker que contenha os vários itens necessários).

Espero que ajude.

Conceder
fonte