[Cross-posted und bearbeitet von https://stackoverflow.com/questions/21933955, da dies für StackOverflow als zu sysadmin-artig angesehen wurde.]
Ich habe einen Docker-Container mit Nginx, der mit einem anderen Docker-Container verknüpft ist. Der Hostname und die IP-Adresse des zweiten Containers werden beim Start als Umgebungsvariablen in den Nginx-Container geladen, sind aber bis dahin nicht bekannt (dynamisch). Ich möchte, dass ich nginx.conf
diese Werte verwende - z
upstream gunicorn {
server $APP_HOST_NAME:$APP_HOST_PORT;
}
Wie kann ich beim Start Umgebungsvariablen in die Nginx-Konfiguration übernehmen?
EDIT 1
Dies ist die gesamte Datei nach der vorgeschlagenen Antwort unten:
env APP_WEB_1_PORT_5000_TCP_ADDR;
# Nginx host configuration for django_app
# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
}
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /static/ {
alias /app/static/;
}
location /media/ {
alias /app/media/;
}
location / {
proxy_pass http://gunicorn;
}
}
Nginx neu laden, dann Fehler:
$ nginx -s reload
nginx: [emerg] unknown directive "env" in /etc/nginx/sites-enabled/default:1
EDIT 2: Weitere Details
Aktuelle Umgebungsvariablen
root@87ede56e0b11:/# env | grep APP_WEB_1
APP_WEB_1_NAME=/furious_turing/app_web_1
APP_WEB_1_PORT=tcp://172.17.0.63:5000
APP_WEB_1_PORT_5000_TCP=tcp://172.17.0.63:5000
APP_WEB_1_PORT_5000_TCP_PROTO=tcp
APP_WEB_1_PORT_5000_TCP_PORT=5000
APP_WEB_1_PORT_5000_TCP_ADDR=172.17.0.63
Root nginx.conf:
root@87ede56e0b11:/# head /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
env APP_WEB_1_PORT_5000_TCP_ADDR;
Site nginx Konfiguration:
root@87ede56e0b11:/# head /etc/nginx/sites-available/default
# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
}
server {
listen 80;
Nginx-Konfiguration neu laden:
root@87ede56e0b11:/# nginx -s reload
nginx: [emerg] directive "server" is not terminated by ";" in /etc/nginx/sites-enabled/default:3
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
mitserver app_web_1:5000;
app_web_1
, wird eine neue IP-Adresse zugewiesen, sodass Sie auch Ihren Nginx-Container neu starten müssen. Docker würde es mit einer aktualisierten Version neu starten,/etc/hosts
sodass Sie die nginx-Konfigurationsdatei (en) nicht ändern müssen.Antworten:
Aus der offiziellen Nginx Docker-Datei:
Aktualisieren:
Aber Sie wissen, dass dies zu seinen Nginx-Variablen wie folgt geführt hat:
beschädigt zu:
Um dies zu verhindern, benutze ich diesen Trick:
Ich habe ein Skript , Nginx zu laufen, die auf der verwendeten
docker-compose
für Nginx - Server - Datei als Befehlsoption, ich nannte esrun_nginx.sh
:Und aufgrund der definierten neuen
DOLLAR
Variablen imrun_nginx.sh
Skript sieht der Inhalt meinernginx.conf.template
Datei für die Nginx-Variable folgendermaßen aus:Und für meine definierte Variable ist das so:
Auch hier gibt es meinen eigentlichen Anwendungsfall.
quelle
proxy_set_header Host $http_host;
command: /bin/bash -c "envsubst '$VAR1 $VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
funktioniert bei mir b / c Ich weiß, wie sie heißen ...$
, sollte seincommand: /bin/bash -c "envsubst '\$VAR1 \$VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
CMD ["/bin/sh","-c", "if [ -n \"${SOME_ENV}\" ]; then echo envsubst '${SOME_ENV}' with ${SOME_ENV} && envsubst '${SOME_ENV}' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf; fi ; nginx -g 'daemon off;'"]
Dies mit Lua zu tun ist wesentlich einfacher als es sich anhört:
Das habe ich hier gefunden:
https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
Bearbeiten:
Dazu muss anscheinend das Lua-Modul installiert werden: https://github.com/openresty/lua-nginx-module
Bearbeiten 2:
Beachten Sie, dass Sie bei diesem Ansatz eine
env
Variable in Nginx definieren müssen :Sie müssen dies im Toplevel-Kontext tun, sonst funktioniert
nginx.conf
es nicht! Nicht im Serverblock oder in der Konfiguration einer Site in/etc/nginx/sites-available
, da sienginx.conf
imhttp
Kontext enthalten ist (was kein Kontext der obersten Ebene ist).Beachten Sie auch, dass Sie bei diesem Ansatz versuchen, eine Umleitung durchzuführen, z.
es wird nicht so gut funktionieren:
Und wenn Sie einen eigenen Variablennamen vergeben:
nginx interpretiert es nicht und leitet Sie weiter zu
https://%24server_name_from_env/
.quelle
env NGINX_SERVERNAME
irgendwo in deiner nginx.conf.set_by_lua
die Variable in der enthaltenen Konfigurationsdatei, während dieenv MY_VAR
Deklaration in der Hauptdatei nginx.conf war, wie vorgeschlagen. Was für eine Schande, das wäre die sauberste Lösung gewesen!envsubst
? Ich vermute, der Vorteil ist, dass Sie denenvsubstr
Befehl nicht ausführen müssen, bevor Sie den Server starten, und der Nachteil ist, dass Sie das Lua-Modul installieren müssen? Ich frage mich, ob beide Ansätze Auswirkungen auf die Sicherheit haben.envsubst
und die in meinem Fall ein No-Go sindIch habe etwas geschrieben, das hilfreich sein kann oder nicht: https://github.com/yawn/envplate
Es bearbeitet Konfigurationsdateien inline mit $ {key} -Verweisen auf Umgebungsvariablen und erstellt optional Backups / protokolliert, was es tut. Es ist in Go geschrieben und die resultierende statische Binärdatei kann einfach von der Registerkarte "Release" für Linux und MacOS heruntergeladen werden.
Es kann auch exec () -Prozesse ausführen, Standardeinstellungen ersetzen, Protokolle erstellen und hat eine sinnvolle Fehlersemantik.
quelle
Das offizielle Nginx-Image empfiehlt die Verwendung
envsubst
, aber wie von anderen hervorgehoben, ersetzt es auch$host
und andere Variablen, was nicht wünschenswert ist. Aber zum Glückenvsubst
kann man als Parameter die Namen der zu ersetzenden Variablen nehmen .Um einen sehr komplexen Befehlsparameter für den Container zu vermeiden (wie im verknüpften Beispiel), können Sie ein Docker-Entypoint-Skript schreiben, das die Umgebungsvariablen vor der Ausführung des Befehls ausfüllt. Das Entrypoint-Skript ist auch ein guter Ort, um die Parameter zu validieren und Standardwerte festzulegen.
Hier ist ein Beispiel für einen Nginx-Container, der
API_HOST
undAPI_PORT
Parameter als Umgebungsvariablen akzeptiert.nginx-default.conf.template
docker-entrypoint.sh
Dockerfile
quelle
Was ich getan habe, war das erb zu benutzen !
--Nach der Verwendung von erb
Dies wird im Cloudfoundry-Buildpack für statische Dateien verwendet
Nginx-Beispielkonfiguration: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf
In deinem Fall
werden
quelle
Bezüglich der Antwort auf die Verwendung von erb kann wie folgt vorgegangen werden.
Schreiben Sie die NGINX-Konfigurationsdatei als erb-Datei, die die Umgebungsvariable enthält, und werten Sie sie mit dem Befehl erb in eine normale Konfigurationsdatei aus.
Innerhalb des Serverblocks der Datei nginx.conf.erb könnte es sein
quelle
erb
kann man eine variable Substitution durchführen ... nachdem der Container gestartet wurde, oder?) - stimmterb
das mit Ruby: stuartellis.name/articles/erbIch weiß, dass dies eine alte Frage ist, aber für den Fall, dass jemand darauf stößt (wie ich es jetzt habe), gibt es einen viel besseren Weg, dies zu tun. Da docker den Alias des verknüpften Containers in / etc / hosts einfügt, können Sie dies einfach tun
vorausgesetzt, Ihr Docker-Befehl ist so etwas wie
docker run --link othercontainer:docker_link_alias nginx_container
.quelle
Eine weitere Option ... Ich habe dieses Tool heute gerade gefunden: https://github.com/kreuzwerker/envplate ... Geschrieben in Go, kann es sehr einfach installiert werden. Die Benutzung ist ganz einfach. Sie müssen jedoch Vorlagenvariablen in Ihre nginx.conf einfügen.
Beispielsweise
${SOME_ENV_VAR}
wird ersetzt, wenn derep
Befehl envplate für die Datei aufgerufen wird. Sollte Ihre Docker-Datei diese Binärdatei nicht erhalten oder aus irgendeinem Grund nicht ausgeführt werden, ist Ihre Konfiguration ungültig. Nur ein kleiner Hinweis im Vergleich zu anderen Lösungen wie der Verwendung von Perl- oder Lua-Erweiterungen.Mir gefällt sehr gut, wie Sie auch Standardwerte festlegen können, wenn die Umgebungsvariable nicht festgelegt ist. Ex.
${SOME_ENV_VAR:default-value}
(und Sie können Werte entkommen). Auch hier muss envplate noch erfolgreich ausgeführt werden.Ein Vorteil eines solchen Ansatzes besteht darin, dass Sie kein Docker-Image haben, das größer als erforderlich ist, da Sie alle Arten von zusätzlichen Modulen installiert haben, die Sie ansonsten nicht benötigen. Es kann auch einfacher sein als sed zu verwenden, wenn die Dinge komplexer werden und diese Standardwertfunktionalität enthalten ist.
quelle
Ich bewerkstellige dies mit einem Shell-Skript.
Hier ist die Nginx-Vorlage:
Und das Skript zum Ersetzen der Umgebungsvariablen ist hier:
quelle
Eine andere Möglichkeit ist, den Befehl 'sed' mit regulären Ausdrücken zu verwenden, dann müssen Sie sich überhaupt nicht mit Ihren Konfigurationsdateien herumschlagen! Auf diese Weise können Sie Ihre Konfigurationsdateien normal verwenden. Wenn Sie jedoch docker ausführen, werden die Werte durch die env-Variablen ersetzt. "Fügen Sie Ihren Konfigurationsdateien, die Sie suchen und durch die Sie ersetzen, keine Textzeichenfolge hinzu."
Sie können mithilfe Ihrer Umgebungsvariablen eine run.sh-Datei mit Ersatzwerten erstellen.
So ändern Sie die "7" in dieser Zeile:
Sed-Befehl mit client_body_timeout als Suchzeile und $ client_body_timeout als Ersatz- Umgebungsvariable :
Kopieren Sie diese Zeile für jeden Parameter, den Sie festlegen möchten, und ändern Sie client_body_timeout mit der Option config und $ client_body_timeout mit der Umgebungsvariablen, der sie zugeordnet ist. Verwenden Sie mit vorhandenen Konfigurationsdatei und es wird nur funktionieren.
quelle
Hier ist ein Beispiel für die Verwendung des
sed
Ansatzes, nicht unbedingt besser, aber es kann für einige nützlich sein. Fügen Sie zunächst ein benutzerdefiniertes Schlüsselwort hinzu, das in der conf-Datei ersetzt werden soll. Zweitens erstellen Sie eine Docker-Datei, die eineENV
Variable deklariert , und anschließend eineCMD
, mitsed
der die Konfiguration bearbeitet wird, bevor nginx explizit ausgeführt wird.Angenommen, Ihre default.conf enthält Folgendes mit dem Schlüsselwort
docker_host
:Und schreiben Sie Ihre Dockerfile ähnlich wie:
Erstellen Sie dann das Image und führen Sie den Container mit aus
quelle
Richtiger Weg, dies mit lua zu tun, da die Antwort oben abgestanden ist:
quelle
Sie sollten in der Lage sein, mit den Vorlagen von Dockerize das zu tun, was Sie wollen .
quelle