¿Puedo usar variables de entorno nginx dentro de archivos estáticos que sirve nginx?

10

Si uso una variable de entorno en la configuración de nginx, y nginx está configurado para servir solo archivos estáticos (html, js, css, por ejemplo, una aplicación AngularJs), ¿hay alguna manera de que pueda usar la variable de entorno dentro de un archivo JS que sirve nginx? ? O es la única forma de hacer esto para ejecutar un servidor no estático, por ejemplo, io.js, php, etc.


Por cierto, no puede usar variables de entorno de forma nativa en la configuración de nginx.

Cuando hablo de variables de entorno en la configuración de nginx me refiero a como en esta publicación: ¿Cómo puedo usar variables de entorno en Nginx.conf donde usan env APP_WEB_1_PORT_5000_TCP_ADDR;y$ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"};


Explique exactamente su caso de uso.

Mi caso de uso específico es que tengo una aplicación AngularJS con tecnología nginx en un contenedor acoplable. La aplicación es una "Aplicación de página única" que consume una API que se ejecuta en otro sistema por completo. Actualmente ejecuto un contenedor docker diferente entre producción y puesta en escena porque la aplicación tiene alguna configuración que es diferente, por ejemplo, el código Google-Analtyics. Estos datos específicos del entorno se guardan en un config.jsarchivo y los valores están actualmente codificados, un valor para la masterrama en git y un valor diferente para la stagingrama. Quiero cambiar el diseño para poder usar el mismo contenedor para producción y puesta en escena. Quiero pasar un ENV var al contenedor cuando lo ejecuto ( docker run -e GACODE=UA-12345-6 ...) y hacer que nginx use el ENV var (via env GACODE;y $ENV{"GACODE"}asíconfig.jsel archivo puede usar los códigos de GoogleAnaltyics que se pasan, en lugar de codificarlos). No sé si esto es posible o no (de ahí la pregunta;)). Usar solo nginx hace que mi contenedor sea un proceso único, mientras que si tengo que usar io.js, necesitaré múltiples contenedores vinculados y más partes móviles son más complejas).

Tom
fuente
Qué ?! Explique exactamente su caso de uso, ya que parece que lo está mirando del lado equivocado. Por cierto, no puede usar variables de entorno de forma nativa en la configuración de nginx.
Xavier Lucas
Gracias @XavierLucas - Actualicé la pregunta para tratar de explicar más.
Tom

Respuestas:

4

sub_filtro

Si desea un simple reemplazo de cadena, puede usar sub_filter . Por ejemplo:

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
}

Sin embargo, no es posible leer una variable de entorno en la configuración de nginx; por supuesto, puede escribir el archivo de configuración de nginx de la forma que necesite / desee producir un archivo de configuración válido y luego volver a cargar nginx.

AD7six
fuente
4

Experimenté con el uso de variables de entorno sub_filter y nginx, pero concluí que no es posible .

Por ejemplo, esto muestra mis experimentos y muestra que el uso de ENV pasados ​​a nginx no funciona dentro de un serverbloque:

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

donde el archivo estático config.json que estoy sirviendo tiene varias cadenas de prueba como las siguientes:

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

Como @ AD7six mencionó, la forma de proceder es tener un script que se ejecute antes de que nginx comience a producir un archivo de configuración válido a partir de marcadores de posición. Pero esto plantea la pregunta, si un script se va a ejecutar antes de que comience nginx, también puedo configurar el contenido de mi config.jsonarchivo en ese script y no molestarme sub_filteren absoluto.

Tom
fuente
2
Si es para un archivo estático, ciertamente tiene sentido no hacerlo a través de la configuración nginx, supuse que su caso de uso era un poco más amplio que eso. Para información / contraste, uso sub_filter "example.com" "example.dev";en una configuración de desarrollo para reemplazar todas y cada una de las referencias del dominio de producción al entorno local porque esas referencias provienen de respuestas de API de terceros / código de aplicación / js / db dumps / etc. - es decir, para nginx podría estar en cualquier lugar en cualquier respuesta html / js / json. +1
AD7six
3

He estado buscando resolver el mismo problema que el OP y esta publicación apareció en la búsqueda de Google, así que pensé en agregar una solución potencial.

Esta publicación describe cómo puede exponer una variable de entorno dentro de la configuración de nginx: https://blog.doismellburning.co.uk/environment-variables-in-nginx-config/

Y puede devolver contenido sin tener un archivo en el sistema de archivos: responda con 200 desde la configuración de Nginx sin servir un archivo

Al poner estas dos cosas juntas terminamos con lo siguiente:

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

Esto me ha funcionado en un entorno de prueba. Es un poco engorroso (no estoy seguro de que sea mejor que generar automáticamente un archivo en el inicio de Docker que contenga los vars que necesita).

Espero que ayude.

Conceder
fuente