Kann ich Nginx-Umgebungsvariablen in statischen Dateien verwenden, die von Nginx bereitgestellt werden?

10

Wenn ich eine Umgebungsvariable in der Nginx-Konfiguration verwende und Nginx so konfiguriert ist, dass nur statische Dateien (HTML, JS, CSS - z. B. eine AngularJs-App) bereitgestellt werden, kann ich die Umgebungsvariable in einer von Nginx bereitgestellten JS-Datei verwenden ? Oder ist die einzige Möglichkeit, dies zu tun, um einen nicht statischen Server auszuführen, z. B. io.js, PHP usw.


Übrigens können Sie Umgebungsvariablen in der Konfiguration von nginx nicht nativ verwenden.

Wenn ich über Umgebungsvariablen in der Nginx-Konfiguration spreche, meine ich wie in diesem Beitrag: Wie kann ich Umgebungsvariablen in der Nginx.conf verwenden, wo sie env APP_WEB_1_PORT_5000_TCP_ADDR;und verwenden$ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"};


Erklären Sie genau Ihren Anwendungsfall

Mein spezieller Anwendungsfall ist, dass ich eine AngularJS-App mit Nginx-Unterstützung in einem Docker-Container habe. Die App ist eine "Einzelseitenanwendung", die eine API verwendet, die insgesamt auf einem anderen System ausgeführt wird. Derzeit führe ich einen anderen Docker-Container zwischen Produktion und Staging aus, da die App eine andere Konfiguration hat, z. B. den Google-Analtyics-Code. Diese umgebungsspezifischen Daten werden in einer config.jsDatei gespeichert und die Werte sind derzeit fest codiert, ein Wert für den masterZweig in Git und ein anderer Wert für den stagingZweig. Ich möchte das Design ändern, damit ich für die Produktion und die Inszenierung denselben Container verwenden kann . Ich möchte eine ENV-Variable an den Container übergeben, wenn ich sie ausführe ( docker run -e GACODE=UA-12345-6 ...) und nginx die ENV-Variable verwenden soll (via env GACODE;und $ENV{"GACODE"}so dieconfig.jsDatei kann die übergebenen GoogleAnaltyics-Codes verwenden, anstatt sie fest zu codieren. Ich weiß nicht, ob dies möglich ist oder nicht (daher die Frage;)). Die Verwendung von nur Nginx macht meinen Container zu einem einzigen Prozess. Wenn ich jedoch io.js verwenden muss, benötige ich mehrere verknüpfte Container und mehr bewegliche Teile sind komplexer.

Tom
quelle
Was ?! Erklären Sie genau Ihren Anwendungsfall, da Sie ihn anscheinend auf der falschen Seite betrachten. Übrigens können Sie Umgebungsvariablen in der Konfiguration von nginx nicht nativ verwenden.
Xavier Lucas
Danke @XavierLucas - Ich habe die Frage aktualisiert, um mehr zu erklären.
Tom

Antworten:

4

sub_filter

Wenn Sie eine einfache Zeichenfolge ersetzen möchten, können Sie sub_filter verwenden . Zum Beispiel:

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
}

Allerdings ist es nicht möglich , eine Umgebungsvariable lesen in nginx Config - Sie natürlich Skript kann das Schreiben der nginx Config - Datei beliebig Sie brauchen / wollen eine gültige Konfigurationsdatei erzeugen und dann neu laden nginx.

AD7six
quelle
4

Ich habe mit der Verwendung von Umgebungsvariablen sub_filter und nginx experimentiert, bin jedoch zu dem Schluss gekommen, dass dies nicht möglich ist .

Dies zeigt zum Beispiel meine Experimente und zeigt, dass die Verwendung von an nginx übergebenen ENVs innerhalb eines Blocks nicht funktioniert 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;
        }
        ...

Dabei enthält die statische Datei config.json, die ich bediene, verschiedene Testzeichenfolgen wie die folgenden:

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

Wie bei @ AD7six erwähnt, müssen Sie ein Skript ausführen, bevor nginx eine gültige Konfigurationsdatei aus Platzhaltern erstellt. Dies wirft jedoch die Frage auf, ob ein Skript vor dem Start von nginx ausgeführt werden soll. Ich kann den Inhalt meiner config.jsonDatei auch in diesem Skript festlegen und mich überhaupt nicht darum kümmern sub_filter.

Tom
quelle
2
Wenn es sich um eine statische Datei handelt - es ist sicherlich sinnvoll, dies nicht über die Nginx-Konfiguration zu tun. Ich habe angenommen, dass Ihr Anwendungsfall etwas breiter ist. Für Informationen / Kontraste verwende ich sub_filter "example.com" "example.dev";in einem Entwicklungs-Setup alle Verweise auf die Produktionsdomäne in der lokalen Umgebung, da diese Verweise aus API-Antworten von Drittanbietern / App-Code / js / db-Dumps / etc. - dh für nginx könnte es irgendwo in einer html / js / json-Antwort sein. +1
AD7six
3

Ich habe versucht, das gleiche Problem wie das OP zu lösen, und dieser Beitrag wurde in der Google-Suche angezeigt. Daher dachte ich, ich würde eine mögliche Lösung hinzufügen.

In diesem Beitrag wird beschrieben, wie Sie eine Umgebungsvariable in der nginx-Konfiguration verfügbar machen können: https://blog.doismellburning.co.uk/environment-variables-in-nginx-config/

Und Sie können Inhalte zurückgeben, ohne eine Datei im Dateisystem zu haben: Antworten Sie mit 200 aus der Nginx-Konfiguration, ohne eine Datei bereitzustellen

Wenn wir diese beiden Dinge zusammenfügen, erhalten wir Folgendes:

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

Dies hat bei mir in einer Testumgebung funktioniert. Es ist etwas umständlich (nicht sicher, ob es besser ist, als beim Docker-Start automatisch eine Datei zu generieren, die die von Ihnen benötigten Variablen enthält).

Ich hoffe, das hilft.

Gewähren
quelle