Docker zum Vierten
Im vorherigen Teil habe ich gezeigt, wie man mit docker-compose eine ganze Gruppe von Containern auf einmal erstellen und starten kann.
Am Ende hatten wir drei Webservices, die man mit http://server.xy:5050
, http://server.xy:4040
und https://server.xy
erreichen konnte.
Das ist machbar, aber nicht besonders elegant, und schon gar nicht intuitiv: Wer kann sich schon merken, welcher Service jetzt 4040 war und welcher 5050? Vor allem, wenn später noch mehr Dienste dazu kommen, wird es leicht unübersichtlich. Ganz davon abgesehen, dass man, wenn man die Dienste von aussen erreichbar machen will, immer mehr Löcher in die Firewall bohren muss.
Wir müssen also noch einen Schritt weiter gehen. Git soll über http://git.server.xy
erreichbar sein, calibre über
http://books.server.xy
und webelexis über https://termine.server.xy
.
Damit das klappt, muss man erst mal sicher stellen, dass diese drei Subdomains via DNS sichtbar sind. Im Fall eines nicht-öffenlichen Servers muss man die Namen in /etc/hosts (Linux) bzw. /private/etc/hosts (Mac), bzw irgendwo anders (Windows) bei allen Clients, die auf den Server zugreifen sollen, eintragen. Beispielsweise mit folgenden Zeilen, die auf ein VPN verweisen:
10.72.82.1 server.xy
10.72.82.1 termine.server.xy
10.72.82.1 git.server.xy
10.72.82.1 books.server.xy
Im Fall eines öffentlich erreichbaren Servers muss man die entsprechenden Einträge beim Nameserver machen (A records). Viele Hosting-Provider nehmen einem diese Arbeit auch ab und ermöglichen in ihrer Administrationsoberfläche die Erstellung von Subdomains. In diesem Fall erledigen sie dann auch gleich den Eintrag im DNS. (Problematischer dürfte eher sein, einen Hosting-Provider zu finden, der Docker anbietet - somit landet man doch wieder beim virtual root server, bei dem man alles selber machen muss.)
Wunderbar, jetzt ist ein und derselbe Server unter vier verschiedenen Namen erreichbar. Oder sogar fünf, wenn man
www.server.xy
mit rechnet. Aber wie kommt nun eine Anfrage zum richtigen Docker-Container? Diesen Job erledigt
ein sogenannter reverse proxy. Ein reverse Proxy nimmt alle Anfragen von aussen entgegen und verteilt sie auf passende
interne Server. Was ‘passend’ für welchen Server ist, muss man in der Konfiguration des Proxys definieren.
Bekanntes Beispiel für einen reverse proxy ist ‘nginx’ (Genauer gesagt: nginx ist vieles, unter anderem auch ein reverse proxy). Leider ist die Konfiguration von nginx ein wenig tricky. Aber glücklicherweise haben andere Docker-User ähnliche Wünsche und Probleme und haben längst passende Lösungen entwickelt. Wir ändern unsere docker-compose.yml wie folgt:
proxy:
image: jwilder/nginx-proxy
ports:
- 80:80
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
owncloud:
image: rgwch/owncloud-client:latest
volumes:
- /srv/ebooks:/srv/owncloud
env_file: ../ebenv.txt
calibre:
image: rgwch/calibre-server:1.0.2
volumes:
- /srv/ebooks:/srv/calibre
environment:
VIRTUAL_HOST: books.meinserver.xy
gitserver:
image: rgwch/git-server:2.0.2
volumes:
- /srv/repositories:/opt/git
environment:
VIRTUAL_HOST: git.meinserver.xy
webelexis:
build: docker-webelexis-server
volumes:
- /home/gerry/dockerfiles/cfglocal.json:/home/webelexis/cfglocal.json:ro
- /home/gerry/dockerfiles/wlxks.jks:/home/webelexis/ks.jks:ro
environment:
VERSION: 1.0.0
VIRTUAL_HOST: termine.meinserver.xy
VIRTUAL_PROTO: https
ports:
- 443:2015
Also mit anderen Worten: Wir starten als erstes jwilder/nginx-proxy und ändern dann die Konfiguration der anderen Dienste so, das wir eine environment-variable namens VIRTUAL_HOST mit dem Namen der gewünschten Subdomain (die dem Eintrag in /etc/hosts bzw. DNS entsprechen muss) ergänzen. Wenn Verbindung über TLS erwünscht ist, muss man zusätzlich VIRTUAL_PROTO: https ergänzen (und natürlich die zur Subdomain passenden Zertifikate bereitstellen)
Das ist eigentlich alles. Im Bruchteil der Zeit, die man zum Aufsetzen eines konventionellen Systems mit diesen Diensten gebraucht hätte, kann man mit Docker und Docker-compose eine ganze Server-Farm aufziehen. Und das Beste: Man kann das alles problemlos in Ruhe auf dem heimischen Computer entwickeln und testen und dann ohne Änderungen auf ein produktives System transferieren.
Das Tüpfelchen auf dem i
Wenn unser eBook-Server öffentlich zugänglich ist, dann stört uns das vermutlich nicht so (Man kann ja nur lesen, nichts kaputt machen), aber möglicherweise verstossen wir damit gegen das Urheberrecht. Wir benötigen daher eine Grenze, die klar macht, dass dies ein privater Server für einen geschlossenen Benutzerkreis ist. Besonders bombensicher muss diese Absicherung nicht sein, es ist die deutliche Grenze, die juristisch relevant ist.
Das macht man so:
- Erstellen Sie ein Unterverzeichnis auth (der Name kann beliebig sein)
- Wechseln Sie in dieses Verzeichnis und geben Sie folgendes ein:
htpasswd -c books.meinserver.xy username
(wobei Sie für username den gewünschten Zugangsnamen einsetzen). Sie werden dann noch nach einem Passwort gefragt, dass Sie Ihrem Lesezirkel anvertrauen müssen.
Dann ergänzen Sie die docker-compose.yml wie folgt:
proxy:
image: jwilder/nginx-proxy
ports:
- 80:80
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /home/gerry/dockerfiles/auth:/etc/nginx/htpasswd
und starten die docker-composition neu. Nun wird jeder Zugriff auf books.meinserver.xy mit einem Passwort gesichert. Sie können beliebig viele dieser Sicherungen anlegen (einfach ein File mit dem VIRTUAL_HOST Namen des zu schützenden Containers um auth Verzeichnis erstellen. Und natürlich kann jede Datei in auth beliebig viele user-Einträge haben.
das Programm htpasswd, das benötigt wird, um die Password-Hashes zu erstellen, ist Teil der apache2-utils. Installieren Sie diese, falls htpasswd nicht gefunden wird. (Sie brauchen nicht den “ganzen” Apache zu installieren).