Reverse Proxy mit Nginx in Docker Container

Docker.io Logo

Das Szenario

– Nginx als SSL Reverse Proxy innerhalb eines Docker Containers
– Externe Domäne www.domain.tld
– Lokaler Webserver auf Port 8080/TCP/HTTP > http://localhost:8080
– Alle Anfragen auf Port 80/TCP/HTTP nach 443/TCP/HTTPS innerhalb des Containers.

Alle Befehle werde ich als Benutzer root ausführen.

Bitte betrachtet den Artikel als Hilfestellung.
Haltet euch immer vorrangig an die offiziellen Dokumentation Nginx‘ und Dockers‘. :-)

Installation Dockers

Debian Wheezy

Installation des Kernels aus dem Backport Repository mit anschließendem Neustart.
Dies ist notwendig, da erst ein Kernel ab Version 3.10 empfohlen wird.

echo deb http://ftp.us.debian.org/debian wheezy-backports main > /etc/apt/sources.list.d/wheezy-backports.list
apt-get update -y
apt-get -t wheezy-backports install linux-image-amd64 -y # Für ein amd64-basierendes System
reboot
OVH VMware vServer Besitzer sollten die Datei „/etc/grub.d/06_OVHkernel“ vor dem Neustart löschen und „update-grub2“ ausführen, damit der neue Kernel aktiv wird.
Der OVH Kernel ist leider etwas beschnitten und bietet unter anderem keine cgroups.

Nun Docker installieren (lassen). Vorab „curl“ installieren:

apt-get install curl
curl -sSL https://get.docker.io/ | bash

Ubuntu 14.04

Ich empfehle den Docker Installer zu verwenden. Es wird das offizielle Repository installiert. Auch hier im Vorfeld „curl“ installieren:

apt-get install curl
curl -sSL https://get.docker.io/ubuntu/ | bash

Konfiguration

Ab hier erst einmal einige Informationen zur Auffrischung der Docker-Kenntnisse:

  • Docker Images werden in der Regel aus dem Repository Dockers‘ gezogen („pull“).
  • Images (Ubuntu, Debian, Centos etc., Debian + Apache, Centos + Nginx und viele mehr) können entweder direkt verwendet- oder durch Dockerfiles manipuliert werden.
  • Docker Images sind für Container immer read-only! Images werden bei Ausführung nie verändert!
  • Ein Container benutzt eine Kopie des Images als Basis. 5 Container mit selben Image, benutzen jeweils eigene Kopien des Images.

Als Grundlage des Reverse Proxys dient das aktuellste (> „latest“) Ubuntu Image „Phusion“, das dem offiziellen Ubuntu Image Dockers‘ einige Optimierungen voraus hat.

Ein Dockerfile erweitert die Basis-Installation um einen Nginx Server aus dem Nginx Repository.

Ein Blick in diese Datei schadet nicht

  • Die Zeile „FROM dockerfile/ubuntu“ ersetzt „sed“ später durch das Phusion Image („phusion/baseimage:latest). Dies ist die Basis.
  • Durch die „RUN“ Befehle wird das Image um Nginx aus dem Nginx PPA erweitert, diesem die Daemon-Funktionalität entzogen (notwendig für Docker) und noch einige weitere Kleinigkeiten angepasst.
  • „VOLUME“ Anweisungen erstellen „mount points“, auf die von außen zugegriffen werden kann.
  • „WORKDIR“ beschreibt das „working directory“ (no shit, Sherlock ;-) ). So werden etwa alle „RUN“ Anweisungen in diesem Verzeichnis ausgeführt.
  • „CMD“ hält die Anweisung bereit, Nginx zu starten.
  • „EXPOSE“ beschreibt die Ports, die im Container während der Laufzeit aktiv sein können.

Alle Daten werde ich im Verzeichnis „/opt“ ablegen. Der letzte Befehl „docker build“ wird das Dockerfile abarbeiten und das veränderte Phusion Image mit der Bezeichnung „phusion/nginx“ ablegen.

mkdir /opt/docker_nginx/ ; cd /opt/docker_nginx
wget -q -O - https://raw.githubusercontent.com/dockerfile/nginx/master/Dockerfile | sed "s/dockerfile\/ubuntu/phusion\/baseimage:latest/g" > Dockerfile
docker build -t="phusion/nginx" .

Hat alles geklappt, schließt die Einrichtung mit „Successfully built XYZ“ ab. Wobei XYZ einer eindeutigen ID entspricht.
Nun besitzt der Host zwei Images, zu prüfen mit „docker images“:

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
phusion/nginx       latest              19c681f50628        36 minutes ago      309.1 MB
phusion/baseimage   latest              cf39b476aeec        8 days ago          289.4 MB

Das Phusion „baseimage“ ist ebenso im lokalen Speicher vorhanden, da es als Basis für das um Nginx erweiterte Image diente.
Dieses könnte durch ein „docker rmi phusion/baseimage“ gelöscht werden, ohne das Nginx Image zu zerstören.

Die Verzeichnisse „/etc/nginx/sites-enabled“, „/etc/nginx/certs“ sowie „/var/logs/nginx“, möchte ich vom Host in den Container mounten, um die Verwaltung zu erleichtern.
Auf dem Host erstelle ich drei Ausgangspunkte für diese Verzeichnisse:

mkdir /opt/docker_nginx/{sites,logs,certs}

Eine einfache Site-Konfiguration für einen Reverse Proxy lege ich unter „sites“ ab:

nano /opt/docker_nginx/sites/reverse_proxy

Inhalt:

server {
        listen 80;
        return 301 https://www.domain.tld/$request_uri;
}
server {
        listen 443;
        server_name www.domain.tld domain.tld;
        ssl on;
        ssl_certificate         /etc/nginx/certs/www.crt;
        ssl_certificate_key     /etc/nginx/certs/www.key;
        ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
        ssl_prefer_server_ciphers on;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        add_header Strict-Transport-Security max-age=15768000;

        location / {

                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_pass      http://localhost:8080;
                proxy_redirect  off;
        }
}

Das Zertifikat und der zugehörige Schlüssel liegen im Verzeichnis „/opt/docker_nginx/certs“. Die Namen (www.*) müssen in der Site entsprechend angepasst werden. Der Pfad bleibt bestehen!

Nun darf der Container mit folgendem Parameter erstmalig gestartet werden:

docker run -p 443:443 -p 80:80 -d -v /opt/docker_nginx/sites:/etc/nginx/sites-enabled -v /opt/docker_nginx/certs:/etc/nginx/certs -v /opt/docker_nginx/logs:/var/log/nginx phusion/nginx

Durch diese Anweisung werden Port 80/TCP sowie 443/TCP vom Host in den Container weitergeleitet, die drei besagten Verzeichnisse eingebunden („-v HOST_VERZ:CONTAINER_VERZ“) und der Container „detached“ gestartet (> nicht-interaktiv, im Hintergrund).

Ein Zugriff auf www.domain.tld leitet ab diesem Punkt auf die lokale Installation auf Port 8080 weiter.

Zur Verwaltung des Containers:

docker ps # Listet gestartete Container
docker ps -a # Listet gestartete und gestoppte Container
docker images # Listet Images
docker stop CONTAINER_ID # Stop einen vorhandenen Container
docker start CONTAINER_ID # Startet einen vorhandenen, gestoppten Container
docker run XYZ # Erstellt (!) einen neuen Container. Nicht mit "start" zu verwechseln!

Eine Antwort auf “Reverse Proxy mit Nginx in Docker Container

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.