Die Docker-Software – eine kurze Einführung

Was ist Docker?

Die Kernfunktionalität der Docker-Software besteht in der Containervirtualisierung von Anwendungen, um eine isolierte Ausführung dieser Anwendung zu erreichen. Hierzu wird der Anwendungs-Code inklusive aller Abhängigkeiten in ein sogenanntes „Docker-Image“ gepackt und mithilfe der „Docker-Engine“ in einem „Docker-Container“ ausgeführt. „Docker-Images“ lassen sich zwischen Systemen bewegen und auf jedem System ausführen, auf dem die Docker-Software läuft und der Linux-Kernel verfügbar ist.

Die Containervirtualisierung ist eine Methode um mehrere Instanzen eines Gastbetriebssystems isoliert voneinander den Kernel des Hostsystems nutzen zu lassen. Somit brauchen die einzelnen Instanzen, die in Containern ausgeführt werden, keine eigenen Kerneldaten, sondern ausschließlich spezifische und zur Ausführung der Applikation notwendige Pakete, wie beispielsweise Bibliotheken, Systemtools, Code und Laufzeit. Dadurch weisen die „Docker-Container“ einen sehr geringen Speicherbedarf, kurze Startzeiten und eine geringe Auslastung des Hostbetriebssystems auf. Obendrein ist die Docker-Software Open Source und auf jedem Betriebssystem, auf dem der Linux-Kernel bereitgestellt wird, verfügbar. Mit der Docker-Software entwickeln sich Software-Architekturen weg von großen, von einander abhängigen Gesamtlösungen und hin zu effizienten und ressourcenschonenden „Microservices“. Wenn wir von Docker als Software sprechen, sollten wir daran denken, dass es sich tatsächlich um mehrere Software-Komponenten handelt, die über die Docker-Engine-API kommunizieren.

Die wichtigsten Komponenten der Docker-Software im Überblick:

Die Docker-Engine:

Die Docker-Engine läuft auf einem lokalen Hostbetriebssystem und besteht aus zwei Komponenten:

Dem Docker-Daemon dockerd:

Dieser wird dauerhaft im Hintergrund ausgeführt und reagiert auf Zugriffe über die Docker-Engine-API. Auf entsprechende Befehle des Docker-Clients über die CLI(command-line interface)-Schnittstelle oder REST(Representational State Transfer)-API hin, verwaltet dockerd Container, Images, Networks oder Volumes.

Dem Docker-Client docker:

Dabei handelt es sich um das oben genannte Kommandozeilenprogramm. Der Docker-Client dient zur direkten Steuerung der Docker-Engine und stellt verschiedene Befehle bereit die an den Docker-Deamon übersendet werden, um von diesem ausgeführt zu werden. Mit dem Docker-Client ist es außerdem möglich mit mehreren Docker-Daemons zu interagieren.

Die Docker-Engine-API:

Bei der Docker-Engine-API handelt es sich um eine REST-API. REST ist ein Designstil für die Client-Server Kommunikation, der sich an dem Verhalten und der Denkweise des World Wide Web orientiert und den Architekturansatz beschreibt, wie verteilte Systeme miteinander kommunizieren können. Durch die vereinheitlichte Kommunikation werden Ressourcen und Zeit gespart.

Die Docker-Engine-API bildet die Schnittstelle zum Docker-Daemon. Zur Integration der API in Software-Projekte stehen offizielle „Software-Development-Kits“ (SKDs) für mehr als ein Dutzend Programmiersprachen zur Verfügung. Damit wird eine Interaktion mit der API vereinfacht und Softwareentwicklern die Wahl gelassen, mit welcher Programmiersprache sie vorzugsweise arbeiten möchten.

Der Zugriff auf die API erfolgt via CLI mit dem Befehl docker.

Die Docker-Tools:

Virtueller Maschinen bestehende oft aus mehreren Software-Komponenten und Services. Im Gegensatz dazu begünstigt Docker einzelne Container als gekoppelte Microservices zu betreiben. Dieses Verhalten eignen sich für verteilte Cloud-Lösungen, die dadurch ein hohes Maß an Modularität und Hochverfügbarkeit bieten.

Es gibt inzwischen unzählige Open-Source-Tools von Drittanbietern, die bereits bestehenden Docker-Tools erweitern, oder die Arbeit mit Docker verbessern. Doch auch Docker bringt einige wichtige Tools mit in den Programmumfang, beispielsweise für die Orchestrierung mehrerer Container.

Docker Swarm:

Mit dem „docker swarm“-Kommando können sich mehrere Docker-Engines zu einer virtuellen Engine zusammenfassen lassen. Dabei stellt es kein Problem dar wenn die einzelnen Docker-Hosts über mehrere Systeme und Infrastrukturen verteilt betrieben werden. Eine Swarm-“node“ beschreibt einen Docker-Hosts als teil eines „Swarms“. Dieser sogenannte „swarm mode“ ermöglicht eine selbstständige Umverteilung von Aufgaben unterhalb der „nodes“, im Falle eines Ausfalls.

Im „swarm mode“ gibt es die Unterteilung der Docker-Hosts in „manager“ und „worker“, wobei die manager-nodes managen und die worker-nodes die Services ausführen, die ihnen von den Managern aufgetragen wurden.

Docker Compose:

Der ‚docker compose‘-Befehl dient zum Erzeugen von Multi-Container-Anwendungen, sprich mehrere isolierte Umgebungen die auf einem Hostsystem betrieben werden. So lassen sich in einem Docker Compose File verschiedene Services definieren, wie auch deren Beziehungen untereinander, die für diese vorgesehenen Ressourcen, Netzwerkangaben, Port-Definitionen und viele mehr. Gestartet wird dieses .yml(YAML)-File mit dem Befehl ‚docker compose up‘, woraufhin der Docker Deamon die Container startet und die vordefinierten Abhängigkeiten automatisiert konfiguriert.

Kubernetes:

Ist ein Open-Source-Orchestration-Programm zur Verwaltung von Container–Anwendungen und wurde ursprünglich von Google entwickelte. Kubernetes hat sich als Standard in der Industrie etabliert und dient Hosting-Firmen und weiteren Anbietern von „Software as a Service“- und „Platform as a Service“-Lösungen als grundlegender Baustein der Infrastruktur. Kubernetes unterstützt ebenfalls komplexe Arbeitsabläufe und eignet sich daher besser für größer angelegte Projekte und Anwendungen, als Docker-Swarm.

Das Docker-Image:

Bei einem Docker-Image handelt es sich um eine schreibgeschützte Blaupause zum Erzeugen eines oder mehrerer identischer Container. Für den Bezug von Docker-Images kommen öffentliche wie auch nichtöffentliche Repositories zum Einsatz, das bekannteste öffentliche Repositories ist vermutlich „Docker Hub“. Es gibt zwei elementar wichtige Docker-Befehle im Bezug auf Docker-Images, diese heißen ‚docker push‘ und ‚docker pull‘.

Über ‚docker push‘ ist es möglich ein bestehendes Docker-Image in das Docker Hub Repositorie hoch zu laden und via ‚docker pull‘ ist es möglich ein Docker-Image aus einem Repositorie herunter zu laden und im weiteren Verlauf dann als Docker-Container auszuführen.

Docker-Images sind in viele Schichten – sogenannten Layers – aufgebaut. Jeder Layer steht für eine Änderung am Image, womit sich eine durchgehende Versionierung der Images ergibt. Mit ‚docker checkpoint‘ lassen sich die verschiedenen Versionen des Images bearbeiten. Zur Erzeugung eines neuen Images kann ein existierendes Image genutzt werden und dieses nach Belieben den gewünschten Anforderungen nach angepasst werden.

Docker-File:

Ein Docker-File ist eine simple Textdatei, die den Aufbau eines Docker-Images beschreibt und als Basis für ein solches Image dient.

Das File ist vergleichbar mit einem Bash-Skript, welches aus sequenziell aufeinanderfolgenden Befehlen besteht und bei der Ausführung die Befehle nacheinander abarbeitet. Für jeden Befehl wird ein neuer Layer im Docker-Image angelegt. Um mit einem Docker-File ein Docker-Image zu erstellen, bedarf es dem Befehl ‚Docker build‘

Docker-Container:

Die wichtigste Komponente von Docker ist der Docker-Container. Dieser repräsentiert eine laufende Instanz eines Images, wobei das Image als Vorlage für den Container dient. Ein Docker-Image liegt auf dem Docker-Host in einer einzigen Kopie vor und benötigt lediglich Speicherplatz. Entgegen dessen lassen sich aus demselben Image mehrere Docker-Container erzeugen und parallel auf dem selben Docker-Host betreiben. Jeder Docker-Container erhält eine vom Administrator selbst definierte Menge an Systemressourcen, oder eine vordefinierte Menge an Systemressourcen vom Docker-Deamon, falls nichts definiert wurde. Regulierbare Systemressourcen sind beispielsweise CPU-Cores, Arbeitsspeicher, Volumes oder Netzwerk-Schnittstellen. Ein Docker-Container lässt sich erzeugen, stoppen, starten und zerstören. Nachdem man einen laufenden Container konfiguriert hat und dieser den eigen Vorstellungen entspricht, kann man den Zustand dieses Containers als neues Image speichern.

Docker und Docker-Compose in der Anwendung:

Um die Docker-Software verwenden zu können, muss zunächst die Docker-Engine installiert werden. Hierzu folgen wir der offiziellen Docker Installationsanleitung und fügen die Docker Repositories unserer Paketverwaltung hinzu. Das Docker-Compose Tool ist ebenso wie Docker-Swarm bereits in den Paketen enthalten.

Als Testsystem wird ein Ubuntu 20.04LTS verwendet.

Zunächst updaten wir das System, installieren grundlegende Programme und bereiten alles für die Docker Repositorys vor:

sudo -i
apt update && apt-get update && apt upgrade -y && apt install -y vim nano ca-certificates curl gnupg lsb-release software-properties-common
init 6
sudo -i

Jetzt folgt das Hinzufügen von Docker’s offizellem GPG(GNU Privacy Guard) key:

mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Nun werden die Docker’s Repositorys hinzugefügt:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Paketquellen aktualisieren:

apt-get update

Schlussendlich Docker-Engine und abhängige Pakete installieren:

apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y

Testing:

docker run hello-world


Um beim Start des Systems Docker auszuführen:

systemctl enable docker

Nachdem wir die Grundvoraussetzungen implementiert haben und die Umgebung testen konnten, wollen wir nun unsere ersten beiden Services auf unserem Docker-Host ausführen. Dazu erstellen wir unsere erste Docker-Compose-Datei.

mkdir $HOME/wordpress
cd && cd wordpress
vim docker-compose.yaml

Diese Konfiguration in das Textdokument kopieren:

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 127.0.0.1:8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:

Unbedingt darauf achten, die Einrückungen mit zu übernehmen!

ACHTUNG!! Die Direktiven:

WORDPRESS_DB_PASSWORD / MYSQL_RANDOM_ROOT_PASSWORD

sollten unbedingt verändert werden! Bitte hierbei beachten, dass bei „WORDPRESS_DB_PASSWORD“ unter dem Service ‚wordpress:‘ das selbe wie bei ‚db:‘ steht!

Jetzt starten wir anhand der Konfiguration die zwei Container, wobei der Schalter -d für ‚detached‘ steht:

docker compose up -d

Wenn wir nun in einen Webbrowser wechseln und auf http://127.0.0.1:8080 wechseln, werden wir mit der Grundkonfiguration von WordPress begrüßt.

Die laufenden Container anzeigen zu lassen, nutzen wir den Befehl:

docker ps -a

Um die Dienste wieder zu stoppen, führen wir im Verzeichniss der Compose-Datei folgendes aus:

docker compose down

Um anstatt einer WordPress-Umgebung eine eigene Nextcloud-Umgebung zu erstellen, nutzt die folgene Konfiguration:

volumes:
  nextcloud:
  db:

services:
  db:
    image: mariadb:10.5
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=test2
      - MYSQL_PASSWORD=test
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  app:
    image: nextcloud
    restart: always
    ports:
      - 127.0.0.1:8080:80
    links:
      - db
    volumes:
      - nextcloud:/var/www/html
    environment:
      - MYSQL_PASSWORD=test
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=db

Und erneut:

docker compose up -d

Wenn wir auch Sie beim Aufbau eines eigenen Docker Servers oder dem Managed Hosting eines Docker Serves unterstützen können, dann nehmen Sie gerne Kontakt auf.