Docker — NGINX Proxy

Was können wir tun wenn wir auf unserem Server mehrere Dienste laufen lassen wollen die aber teilweise den gleichen Port nutzen oder wir einen Dienst auf einer bestimmten Domain haben wollen? Genau, wir nutzen dafür einen Proxy. Hier bietet sich ein NGINX Proxy an, dieser ist schnell und verbraucht nur wenig der Server Ressourcen. Doch wie können wir das umsetzen?

Der klassische Weg ist einen Container mit dem offiziellen NGINX Image zu erstellen und diesem eine Konfiguration mitzugeben in der unsere Proxy Einstellung steht. Das funktioniert, ist aber umständlich. Starten wir einen neuen Container bekommt dieser eine IP von Docker die wir vorher nicht wissen, auch wissen wir nicht ob sich diese oder der Port noch einmal ändert z.B. bei einem neu erstellen des Containers aufgrund einer neuen Version der App. Das macht es schwer alle Änderungen von Hand zu tätigen.

Das hat sich wohl auch Jason Wilder gedacht und hat ein fantastisches Docker Image gebaut was uns diese Arbeit abnimmt.

Die Basis ist auch hier das offizielle NGINX Docker Image was als Proxy fungiert. Diese Image beinhaltet aber https://github.com/jwilder/docker-gen was auf dem Docker Socket lauscht und uns entsprechend eine Konfiguration für NGINX schreibt und diese während der Laufzeit einspielt. Das heißt wir haben keine Downtime oder ähnliches wenn wir einen Dienst hinzufügen oder ändern.

Starten des NGINX Proxy

Das starten des Proxies ist wie zu erwarten sehr einfach und geht wie folgt:

docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

Jetzt läuft unser Proxy auf Port 80 und lauscht auf /var/run/docker.sock im Read-Only Modus. Ab jetzt überwacht docker-gen, was im Container läuft, unseren Docker Socket auf Container Änderungen wie Start und Stop. Wird eine Änderung registriert wird die Konfiguration angepasst und der NGINX Proxy macht ein Reload um diese neu zu laden.

Wenn wir jetzt auf unsere IP/Domain gehen müsste ein 503 Service Temporarily Unavailable erscheinen. Das zeigt uns das der Proxy läuft und funktioniert.

Container starten

Jetzt wo unser Proxy läuft können wir unseren Container starten der auf unsere Domain geroutet werden soll. In diesem Beispiel starten wir einen Container mit Ghost der Blogging Software auf der Domain: example.com

Ohne den Proxy würden wir den Container wie folgt starten:

docker run -d --name ghost -p 8000:2368 ghost

Jetzt wäre unser Blog unter example.com:8000 zu erreichen. Damit kann aber niemand was anfangen und wir wollen das Blog ohne Port erreichen. Also starten wir diesmal mit unserem Proxy:

docker run -d --name ghost -e VIRTUAL_HOST=example.com ghost

Das war es schon. Nun ist das Blog unter http://example.com zu erreichen. Sicher fragst du dich warum wir hier keinen Port mit angegeben haben und das ist auch eine berechtigte Frage. Der Proxy entscheidet selbst welchen Port er zum weiterleiten benutzt. Das funktioniert aber nur wenn der Container den wir starten (in diesem Fall Ghost) nur einen Port exposed. Sollte der Container mehrere Ports haben so müssen wir dem Proxy mitteilen auf welchem er zu erreichen ist. Dann sieht unser Startbefehl wie folgt aus:

docker run -d --name ghost -e VIRTUAL_HOST=example.com -e VIRTUAL_PORT=2368 ghost

Damit weiß der Proxy jetzt das alle Anfragen auf der URL example.com auf den Ghost Container geleitet werden sollen und dort speziell auf den Port 2368. Somit sind auch Container die mehreren Ports haben kein Problem.

Das ganze kann natürlich auch mit einer docker-compose.yml gestartet werden:

version: '2'
services:
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
volumes:
- var/run/docker.sock:/tmp/docker.sock:ro
ghost:
image: ghost
container_name: ghost
environment:
- VIRTUAL_HOST=example.com
- VIRTUAL_PORT=2368

Anschließend kann alles mit einem:

docker-compose up -d

gestartet werden.

Weitere Konfiguration und Optionen

Der nginx-proxy Container bietet aber noch viel mehr Optionen und Konfigurationsmöglichkeiten. Diese findet Ihr alle im GitHub Repo: https://github.com/jwilder/nginx-proxy

Show your support

Clapping shows how much you appreciated Lars Hampe’s story.