von Stephan Makowski
Manchmal möchte ich schnell mal etwas testen. Da ich regelmäßig mit Softwarelösungen arbeite, die hauptsächlich unter Linux laufen, setze ich mir für Testzwecke eine virtuelle Maschine auf. Das geht, ist aber recht ressourcenhungrig. Egal, ob unter Hyper-V oder Virtual Box. Möchte ich mehr als zwei Maschinen gleichzeitig laufen lassen, hat mein Rechner irgendwann eben keinen Speicher mehr. Also muss ich mir etwas anderes einfallen lassen.
Die beste Lösung hierfür ist ohne Zweifel ein Docker-Setup. Bei Docker handelt es sich um eine Containerlösung. Vereinfacht gesagt bedeutet das, dass auf dem Host ein Dockerservice installiert wird. Nach der Installation können beliebig viele (je nachdem, was der Rechner/Server so hergibt) Web-/Mailserver, Datenbanken, WordPressinstanzen, etc. gestartet und gemanaged werden. Eine Übersicht über die möglichen Container, die unter Docker laufen, ist auf Docker Hubs zu finden.
Das Schöne daran ist: Die meiste Software, z. B. Apache, MySQL oder Neo4J, ist direkt ohne weitere Programmierkenntnisse einsetzbar. Die Container werden runtergeladen, individuell konfiguriert und in der Dockerumgebung gestartet. Klingt einfach? Ist es auch. Wer mir nicht glaubt, kann das hier direkt mal nachlesen.
Docker compose – dein Freund und Helfer
Inwiefern ist das also auch für die Digital Humanities interessant? In etlichen Bereichen werden NoSQL Datenbanken wie eXist-db oder BaseX eingesetzt. Auch diese Datenbanken sind bereits als vorbereitete Dockerimages zu haben.
Möchte man solch eine Konfiguration öfter mal testen, tut man gut daran, eine sogenannte docker-compose-Datei zu schreiben. Hierbei handelt es sich um eine Art Beschreibung, welches Image Docker laden soll und wie dieses zu konfigurieren und zu starten ist.
Im Juni 2021 wurde eine neue NoSQL-Datenbank mit dem Namen FusionDB veröffentlicht. Zu Testzwecken habe ich hierfür eine docker-compose-Datei erstellt, die ich im Folgenden präsentieren möchte:
version "3" services: fusiondb: image: fusiondb build: context: ./conf dockerfile: ./Dockerfile args: PASSWORD: ${PASSWORD} INIT_MEMORY: ${INIT_MEMORY:-256} MAX_MEMORY: ${MAX_MEMORY:-2048} CACHE_SIZE: ${CACHE_SIZE:-256} COLLECTION_CACHE: ${COLLECTION_CACHE:-256} LUCENE_BUFFER: ${LUCENE_BUFFER:-256} HTTP_PORT: ${HTTP_PORT:-4059} HTTPS_PORT: ${HTTPS_PORT:-5059} SERVER_NAME: ${SERVER_NAME:-localhost} volumes: - data:/opt/fusiondb/fusiondb-server-1.0.0-ALPHA1/data ports: - 4059:4059 - 5059:5059 container_name: fusiondb restart: always networks: - www labels: - "traefik.backend=fusiondb-backend" - "traefik.docker.network=www" - "traefik.frontend.rule=Host:fusiondb.stephan-makowski.de" volumes: data: {} networks: www: external: name: ${TRAEFIK_NETWORK:-www}
docker-compose.yml
In dieser Datei soll ein Dienst mit dem Namen fusiondb erstellt werden. Hierfür gibt es (noch) kein fertiges Image, sodass dieses vorab erstellt werden muss. Die Anweisungen, welche und wie eine Erstellung vorgenommen werden soll, befinden sich in der Datei “Dockerfile” (s. unten).
Ein wichtiger Vorteil von Docker ist die EInrichtung sogenannter Volumes. Hierbei handelt es sich um (permanente) Verzeichnisse, die zur Laufzeit innerhalb des Containers gemounted werden. Es sind sozusagen Ordner, die an einer bestimmten Stelle eingehangen werden. An dieser Stelle soll das Volume data an das Verzeichnis /opt/fusiondb/fusiondb-server-1.0.0-ALPHA1/data angehangen werden. Wozu? Die Volumes können vom Host gesichert werden. Außerdem wird so sichergestellt, dass die Daten persistent vorgehalten werden. Ohne solch ein Volume würde bei jedem Start der Ursprungszustand des Images wiederhergestellt werden. Das ist bei Datenbanken etwas unpraktisch.
Die meisten Dienste im Internet sind über Portangaben zu erreichen. Für die Internetseiten ist es meist der Port 80, der als Standard für alle eingehenden Http-Anfragen genutzt wird. Der Service fusiondb soll allerdings auf eingehende Anfragen auf den Port 4059 (http) sowie 5059 (https) lauschen. Die Angaben können hier ganz leicht gesetzt werden. Oft kommt es aber vor, dass zwei unterschiedliche Dienste denselben Port nutzen. In diesem Fall kann in der Datei eine Zuweisung vorgenommen werden, welcher Port alternativ abgehört werden soll. Die Notation hierfür ist:
-ports:
– externer Port: interner Port
Damit wird eine Art Weiterleitung eingerichtet, die für jeden Dockercontainer genutzt werden kann.
Die folgenden Definitionen geben an, wie der Service heißt, welches interne Routingnetzwerk genutzt werden soll und ob ergänzende Informationen benötigt werden. In meinem Fall habe ich noch Angaben für den Routerservice Traefik gemacht. Abschließend folgen die Definitionen der Netzwerke sowie der Volumes. An dieser Stelle sei auf die gute Dokumentation von Docker verwiesen.
Wenn man kein Image hat, baut man sich halt eines
Wie bereits erwähnt, gibt es derzeit für fusiondb noch kein Dockerimage. Da ich dieses aber gern testen wollte und für zukünftige Updates bereits vorbereitet sein möchte, erstelle ich mir das Image selbst.
Im Grunde folgt die Datei dem Aufbau:
-
- Welche Basis soll benutzt werden?
- Was soll innerhalb der Basis gemacht werden?
- Wie ist das Image ansprechbar und wie soll Docker die Inhalte ansprechen?
ARG BASE_CONTAINER=ubuntu:latest FROM $BASE_CONTAINER LABEL maintainer="Stephan Makowski <stephan.makowski@rub.de>" USER root ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8" ARG PASSWORD ARG INIT_MEMORY=256 ARG MAX_MEMORY=2048 ARG CACHE_SIZE=256 ARG COLLECTION_CACHE=256 ARG LUCENE_BUFFER=256 ARG HTTP_PORT=8080 ARG HTTPS_PORT=8443 ARG SERVER_NAME='localhost' RUN apt-get update && apt-get -yq dist-upgrade &&\ apt-get install -yq --no-install-recommends \ sudo \ curl \ htop \ default-jdk \ unzip \ vim \ wget &&\ rm -rf /var/lib/apt/lists/* WORKDIR /opt/fusiondb RUN wget http://www.fusiondb.com/download/fusiondb-server-1.0.0-ALPHA1-unix.tar.bz2 RUN tar xjf ./fusiondb-server-1.0.0-ALPHA1-unix.tar.bz2 WORKDIR /opt/fusiondb/fusiondb-server-1.0.0-ALPHA1 VOLUME /opt/fusiondb/fusiondb-server-1.0.0-ALPHA1/data RUN echo '#!/bin/bash' >> /usr/local/bin/docker-entrypoint.sh &&\ echo 'set -e' >> /usr/local/bin/docker-entrypoint.sh &&\ echo 'cd /opt/fusiondb/fusiondb-server-1.0.0-ALPHA1' >> /usr/local/bin/docker-entrypoint.sh &&\ echo 'sudo bin/startup.sh' >> /usr/local/bin/docker-entrypoint.sh &&\ chmod +x /usr/local/bin/docker-entrypoint.sh EXPOSE ${HTTP_PORT} ${HTTPS_PORT} HEALTHCHECK --interval=1m --timeout=3s \ CMD curl -f http://localhost:4059/ || exit 1 ENTRYPOINT ["docker-entrypoint.sh"]
Dockerfile
Kurz zusammengefasst soll das Image für die Datenbank das letzte verfügbare Ubuntu als Ursprungsbetriebssystem nutzen. Anschließend erfolgt eine Aktualisierung und die Installation benötigter Komponenten wie z. B. Java. Im nächsten Arbeitsschritt lädt Docker dann die Datenbank herunter, entpackt diese und kopiert das Startskript, damit dieses von Docker ausgeführt werden kann.
Mir war bewusst, dass es sicherlich nicht die eleganteste Lösung ist, und wollte noch weitere Verarbeitungsschritte einarbeiten. Deshalb sind noch einige etwas kryptische Argumente enthalten. Und: Es funktioniert. Das erlaubt mir schon mal vorab, fleißig zu testen. Sollte in naher Zukunft eine aktualisierte Version der fusiondb herauskommen, bin ich vorbereitet.
Die Skripts können vollständig aus meinem Gitlab heruntergeladen werden.
Routing mit Traefik
Egal, ob Datenbank, Webpages oder andere Tools: selten werden die Dienste über nur einen Domainnamen angesprochen. So macht es Sinn, explizite Namen bzw. Subdomains für die unterschiedlichen Dienste zu verwenden. Während eine x-beliebige API unter api.meine-domain.de erreichbar ist, kann das obere Beispiel unter fusion.meine-domain.de laufen. Diese sinnstiftende syntaktische Unterscheidung vereinfacht die Nutzung wesentlich. Eine Möglichkeit, dies zu erreichen, ist die Verwendung des Dienstes traefik. Hierbei handelt es sich um einen Routingdienst, der sowohl per Docker als auch nativ auf dem Server betrieben werden kann. Die Nutzung ist denkbar einfach. Die jeweiligen Subdomains (www, api, db, etc.) werden im Domain Name Server (DNS) der Domain angelegt und verweisen dort zentral auf den Server (per IP). Wie ein jeweiliger Dienst angesprochen werden kann, muss separat in der docker-compose Datei hinterlegt werden.
labels:
– “traefik.backend=fusiondb-backend”
– “traefik.docker.network=www”
– “traefik.frontend.rule=Host:fusiondb.stephan-makowski.de”
Der Dienst wäre in diesem Beispiel nun unter fusiondb.stephan-makowski.de zu erreichen. Die Notation unterscheidet sich aber je nach verwendeter Traefik-Version. Mit dem Upgrade auf Traefik V2.0 ist die Auszeichnung zwar etwas umfangreicher geworden, erlaubt im Gegenzug aber eine vielfältigere Konfiguration. Eine Übersicht über sämtliche Funktionalitäten kann hier schwerlich geleistet werden. Vielmehr dient diese Übersicht lediglich als erster Eindruck.
labels:
– traefik.enable=true
– traefik.http.routers.hp.entrypoints=http
– traefik.http.routers.hp.rule=Host(`fusiondb.stephan-makowski.de`)
– traefik.http.middlewares.hp-https
-redirect.redirectscheme.scheme=https
– traefik.http.routers.hp.middlewares=hp-https-redirect
– traefik.http.routers.hp-secure.entrypoints=https
– traefik.http.routers.hp-secure.rule=Host(`fusiondb.stephan-makowski.de`)
– traefik.http.routers.hp-secure.tls=true
– traefik.http.routers.hp-secure.tls.certresolver=http
Die Notation ist teilweise variabel. So ist die grundlegende Syntax:
– traefik.http.[middlewares/routers].[Abkürzung des Dienstes].etc
Es muss beachtet werden, dass jeder Dienst sein eigenes Namenschema enthält. Ansonsten kann eine Auflösung des Dienstes nicht erfolgen.
Beispiel:
– traefik.http.routers.hp.rule=Host(`www.stephan-makowski.de`)
– traefik.http.routers.api.rule=Host(`api.stephan-makowski.de`)
-traefik.http.routers.fusion.rule=Host(`fusiondb.stephan-makowski.de`)
Ausblick
Ob eine kleine NoSQL-Datenbank zum Testen, eine WordPressinstanz als Projektseite oder ein Cluster, der über mehrere Server Ausfallsicherheit bietet: All das kann Docker und noch mehr. Und das Wichtigste: Das System ist kostenfrei erhältlich und nutzbar. Die Zeiten, in denen in langwierigen Verfahren an Rechenzentren Server beantragt werden mussten, sind vorbei. Denn Docker ist ein wunderbares Werkzeug und erleichtert einem massiv die Arbeit. Außerdem ersparen Dienste wie Traefik eine tiefgründige Beschäftigung mit Apache oder Nginx und macht Docker sowohl für IT-Expert*innen als auch für Laien interessant.
Für einen Austausch zu dem Thema stehe ich gern zur Verfügung.
Weiterführende Links
Überarbeitete Fassung des Blogbeitrags vom 17. Juni 2019 auf https://blog.stephan-makowski.de