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 Ressourcen-hungrig. Egal, ob unter Hyper-V oder Virtual Box. Irgendwann hat mein Rechner möchte ich mehr als zwei Maschinen gleichzeitig laufen lassen, halt 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 ist direkt ohne weitere Programmierkenntnisse einsetzbar, z.b. Apache, MySQL oder Neo4J. Die Container werden sozusagen 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. Diese Datenbanken sind ebenfalls bereits als vorbereitete Dockerimages zu haben.

Möchte man solch eine Konfiguration öfters mal testen, tut man sich 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 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 was und wie die Erstellung vorgenommen wird, befinden sich in der Datei "Dockerfile", die im weiteren Verlauf dieses Beitrages ebenfalls besprochen werden soll.

Ein wichtiger Vorteil von Docker ist, dass diese über sogenannte Volumes verfügen können. Hierbei handelt es sich um (permanente) Verzeichnisse, die zur Laufzeit innerhalb des Containers gemounted werden sollen. Es sind sozusagen Ordner, die an einer bestimmten Stelle eingehangen werden sollen. An dieser Stelle soll das Volume data an das Verzeichnis /opt/fusiondb/fusiondb-server-1.0.0-ALPHA1/data angehangen werden. Wieso wird dieses gemacht? Die Volumes können vom Host her gesichert werden. Außerdem sorgt dieses dafür, dass die Daten persistent vorgehalten werden. Ohne solch ein Volume, würde bei jedem Start wieder der Ursprungszustand des Images wiederhergestellt werden. Das ist bei Datenbanken etwas unpraktisch.

Die meisten Dienste im Internet sind per sogenannte 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 den selben 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
Es ist also eine Art Weiterleitung und kann für jeden Dockercontainer genutzt werden.

Die folgenden Definitionen geben schließlich noch 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 die Angaben für den Routerservice Traefik angegeben. Abschließend folgen die Definitionen der Netzwerke sowie der Volumen. 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 fusiondbnoch kein Dockerimage. Da ich aber dieses aber gern testen wollte und für zukünftige Updates bereits vorbereitet sein möchte, erstelle ich mir das Image halt 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 <[email protected]>"

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 als auch die Installation benötigter Komponenten, wie Java. Im folgenden Arbeitsschritt lädt Docker dann die Datenbank herunter, entpackt diese und kopiert das Startskript, damit dieses von Docker ausgeführt werden kann.

Mir ist klar, dass es sicherlich nicht die eleganteste Lösung ist und wollte noch weitere Verarbeitungsschritte einarbeiten. Deshalb sind noch einige etwas kryptische Argumente enthalten. Aber es ist soweit lauffähig. Und das erlaubt mir schon mal vorab fleißig zu testen. Sollte in naher Zukunft eine aktualisierte Version heraus kommen, bin ich vorbereitet.

Die Skripts können vollständig aus meinem Gitlab heruntergeladen werden.

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. Für einen Austausch zu dem Thema, stehe ich gern zur Verfügung.