Die Antwort von @ T0xicCode ist richtig, aber ich dachte, ich würde die Details erweitern, da ich tatsächlich ungefähr 20 Stunden gebraucht habe, um endlich eine funktionierende Lösung zu implementieren.
Wenn Sie Nginx in einem eigenen Container ausführen und als Reverse-Proxy verwenden möchten, um mehrere Anwendungen auf derselben Serverinstanz auszugleichen, müssen Sie die folgenden Schritte ausführen:
Verknüpfen Sie Ihre Container
Wenn Sie docker run
Ihre Container verwenden, in der Regel durch Eingabe eines Shell-Skripts User Data
, können Sie Links zu anderen laufenden Containern deklarieren . Dies bedeutet, dass Sie Ihre Container in der richtigen Reihenfolge starten müssen und nur die letzteren Container mit den ersteren verknüpft werden können. Wie so:
#!/bin/bash
sudo docker run -p 3000:3000 --name API mydockerhub/api
sudo docker run -p 3001:3001 --link API:API --name App mydockerhub/app
sudo docker run -p 80:80 -p 443:443 --link API:API --link App:App --name Nginx mydockerhub/nginx
So in diesem Beispiel das API
wird Behälter aller anderen nicht verbunden, aber der
App
Behälter verknüpft ist API
und Nginx
auf beide verbunden API
und App
.
Das Ergebnis sind Änderungen an den env
Variablen und /etc/hosts
Dateien, die sich in den Containern API
und befinden App
. Die Ergebnisse sehen so aus:
/ etc / hosts
Wenn Sie cat /etc/hosts
in Ihrem Nginx
Container ausgeführt werden, wird Folgendes erzeugt:
172.17.0.5 0fd9a40ab5ec
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 App
172.17.0.2 API
ENV Vars
Wenn Sie env
in Ihrem Nginx
Container ausgeführt werden, wird Folgendes erzeugt:
API_PORT=tcp://172.17.0.2:3000
API_PORT_3000_TCP_PROTO=tcp
API_PORT_3000_TCP_PORT=3000
API_PORT_3000_TCP_ADDR=172.17.0.2
APP_PORT=tcp://172.17.0.3:3001
APP_PORT_3001_TCP_PROTO=tcp
APP_PORT_3001_TCP_PORT=3001
APP_PORT_3001_TCP_ADDR=172.17.0.3
Ich habe viele der tatsächlichen Variablen abgeschnitten, aber die oben genannten sind die Schlüsselwerte, die Sie benötigen, um den Datenverkehr auf Ihre Container zu übertragen.
Verwenden Sie Folgendes, um eine Shell zum Ausführen der oben genannten Befehle in einem laufenden Container zu erhalten:
sudo docker exec -i -t Nginx bash
Sie können sehen, dass Sie jetzt sowohl /etc/hosts
Dateieinträge als auch env
Variablen haben, die die lokale IP-Adresse für einen der verknüpften Container enthalten. Soweit ich das beurteilen kann, ist dies alles, was passiert, wenn Sie Container mit deklarierten Linkoptionen ausführen. Sie können diese Informationen jetzt jedoch zum Konfigurieren nginx
in Ihrem Nginx
Container verwenden.
Nginx konfigurieren
Hier wird es etwas knifflig und es gibt einige Möglichkeiten. Sie können Ihre Sites so konfigurieren, dass sie auf einen Eintrag in der erstellten /etc/hosts
Datei verweisen docker
, oder Sie können die ENV
vars verwenden und einen String-Ersatz (den ich verwendet habe sed
) für Ihre nginx.conf
und alle anderen conf-Dateien ausführen, die sich möglicherweise in Ihrem /etc/nginx/sites-enabled
Ordner befinden, um die IP einzufügen Werte.
OPTION A: Konfigurieren Sie Nginx mit ENV Vars
Dies ist die Option, die ich gewählt habe, weil ich die Dateioption nicht
/etc/hosts
zum Laufen bringen konnte. Ich werde Option B früh genug ausprobieren und diesen Beitrag mit allen Ergebnissen aktualisieren.
Der Hauptunterschied zwischen dieser Option und der Verwendung der /etc/hosts
Dateioption besteht darin, wie Sie schreiben Dockerfile
, um ein Shell-Skript als CMD
Argument zu verwenden, das wiederum das Ersetzen der Zeichenfolge zum Kopieren der IP-Werte ENV
in Ihre Conf-Datei (en) übernimmt.
Hier sind die Konfigurationsdateien, mit denen ich am Ende fertig war:
Dockerfile
FROM ubuntu:14.04
MAINTAINER Your Name <you@myapp.com>
RUN apt-get update && apt-get install -y nano htop git nginx
ADD nginx.conf /etc/nginx/nginx.conf
ADD api.myapp.conf /etc/nginx/sites-enabled/api.myapp.conf
ADD app.myapp.conf /etc/nginx/sites-enabled/app.myapp.conf
ADD Nginx-Startup.sh /etc/nginx/Nginx-Startup.sh
EXPOSE 80 443
CMD ["/bin/bash","/etc/nginx/Nginx-Startup.sh"]
nginx.conf
daemon off;
user www-data;
pid /var/run/nginx.pid;
worker_processes 1;
events {
worker_connections 1024;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 33;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 64;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging Settings
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Gzip Settings
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 3;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/xml text/css application/x-javascript application/json;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
# Virtual Host Configs
include /etc/nginx/sites-enabled/*;
# Error Page Config
#error_page 403 404 500 502 /srv/Splash;
}
HINWEIS: Es ist wichtig, diese daemon off;
in Ihre nginx.conf
Datei aufzunehmen, um sicherzustellen, dass Ihr Container nicht sofort nach dem Start beendet wird.
api.myapp.conf
upstream api_upstream{
server APP_IP:3000;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://api.myapp.com/$request_uri;
}
server {
listen 443;
server_name api.myapp.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_pass http://api_upstream;
}
}
Nginx-Startup.sh
#!/bin/bash
sed -i 's/APP_IP/'"$API_PORT_3000_TCP_ADDR"'/g' /etc/nginx/sites-enabled/api.myapp.com
sed -i 's/APP_IP/'"$APP_PORT_3001_TCP_ADDR"'/g' /etc/nginx/sites-enabled/app.myapp.com
service nginx start
Ich überlasse es Ihnen, Ihre Hausaufgaben über die meisten Inhalte von nginx.conf
und zu machen api.myapp.conf
.
Die Magie entsteht dort, Nginx-Startup.sh
wo wir sed
den APP_IP
Platzhalter, den wir in den geschrieben haben, durch Zeichenfolgen ersetzenupstream
Block unserer api.myapp.conf
und app.myapp.conf
-Dateien geschrieben haben.
Diese ask.ubuntu.com-Frage erklärt es sehr gut:
Suchen und Ersetzen von Text in einer Datei mithilfe von Befehlen
GOTCHA Behandelt unter
OSX sed
Optionen unterschiedlich, insbesondere das -i
Flag. Unter Ubuntu -i
übernimmt das Flag den Ersatz "an Ort und Stelle". Es öffnet die Datei, ändert den Text und speichert dieselbe Datei. Unter OSX erfordert das -i
Flag die Dateierweiterung, die die resultierende Datei haben soll. Wenn Sie mit einer Datei ohne Erweiterung arbeiten, müssen Sie '' als Wert für das eingeben-i
Flag eingeben.
GOTCHA
Um ENV-Variablen innerhalb des regulären Ausdrucks zu verwendensed
mit dem die zu ersetzende Zeichenfolge gefunden wird, müssen Sie die in doppelte Anführungszeichen setzen. Die korrekte, wenn auch wackelig aussehende Syntax lautet also wie oben.
Daher hat Docker unseren Container gestartet und die Nginx-Startup.sh
Ausführung des Skripts ausgelöst , mit dem sed
der Wert APP_IP
in die entsprechende ENV
Variable geändert wurde , die wir im sed
Befehl angegeben haben. Wir haben jetzt conf-Dateien in unserem /etc/nginx/sites-enabled
Verzeichnis, die die IP-Adressen der ENV
Variablen enthalten, die Docker beim Starten des Containers festgelegt hat. In Ihrer api.myapp.conf
Datei sehen Sie, dass sich der upstream
Block wie folgt geändert hat:
upstream api_upstream{
server 172.0.0.2:3000;
}
Die IP-Adresse, die Sie sehen, kann unterschiedlich sein, aber ich habe festgestellt, dass dies normalerweise der Fall ist 172.0.0.x
.
Sie sollten jetzt alles entsprechend routen.
GOTCHA
Sie können keine Container neu starten / erneut ausführen, sobald Sie den ersten Instanzstart ausgeführt haben. Docker stellt jedem Container beim Start eine neue IP-Adresse zur Verfügung und scheint keine zuvor verwendete IP-Adresse wiederzuverwenden. So api.myapp.com
wird beim ersten Mal 172.0.0.2, beim nächsten Mal 172.0.0.4. Aber Nginx
wird bereits die erste IP in seine conf - Dateien festgelegt, oder in seiner /etc/hosts
Datei, so wird es nicht möglich sein , für die neue IP zu bestimmen api.myapp.com
. Die Lösung hierfür wird wahrscheinlich CoreOS
und ihr etcd
Dienst verwendet, der nach meinem begrenzten Verständnis ENV
für alle im selben CoreOS
Cluster registrierten Computer wie eine gemeinsame Lösung fungiert . Dies ist das nächste Spielzeug, mit dem ich spielen werde.
OPTION B: Verwenden Sie /etc/hosts
Dateieinträge
Dies sollte der schnellere und einfachere Weg sein, aber ich konnte es nicht zum Laufen bringen. Angeblich haben Sie nur den Wert des /etc/hosts
Eintrags in Ihre api.myapp.conf
und app.myapp.conf
Dateien eingegeben , aber ich konnte diese Methode nicht zum Laufen bringen.
UPDATE:
Siehe die Antwort von @Wes Tod für Anweisungen, wie diese Methode funktioniert.
Hier ist der Versuch, den ich gemacht habe api.myapp.conf
:
upstream api_upstream{
server API:3000;
}
In Anbetracht dessen, dass es einen Eintrag in meinem gibt /etc/hosts
Datei wie den folgenden enthält: 172.0.0.2 API
Ich dachte, er würde nur den Wert abrufen, aber es scheint nicht so zu sein.
Ich hatte auch ein paar zusätzliche Probleme mit meiner Elastic Load Balancer
Beschaffung von allen AZs, so dass dies möglicherweise das Problem war, als ich diese Route ausprobierte. Stattdessen musste ich lernen, wie man unter Linux mit dem Ersetzen von Strings umgeht, also hat das Spaß gemacht. Ich werde es gleich versuchen und sehen, wie es geht.