Docker

Kürzlich habe ich mit einem CTO eines bekannten Schweizer Software-Entwicklungs-Unternehmens gesprochen und natürlich ist das Thema DevOps, Continuous Deployment und das Verpacken eines Software-Release für das Deployment gefallen, für das auch das Software-Entwicklungs-Unternehmen bereits erste Erfahrungen mit Docker gesammelt hat. Zu meinem grossen Erstaunen hat mein Gesprächspartner gemeint er habe keinen Betriebspartner bzw. Hoster für Docker in der Schweiz gefunden. Darum möchten wir unser Angebot für Docker-Hosting in der Schweiz offiziell launchen!

Die verschiedenen Komponenten des Docker-Universums helfen dabei die standardisierten Container zu erstellen, kombinieren und zu betreiben.

Docker Engine

Die Docker Engine ist, was die meisten meinen, wenn sie von „Docker“ sprechen und besteht aus zwei Teilen:

  1. Das Programm „docker“, welches vom Benutzer gesteuert wird.
  2. Dem Docker-Dienst (Docker Daemon, dockerd) welches die Befehle von „docker“ im Hintergrund ausführt.

Die Engine ist damit der Kern der Technologie und das Zentrum des Docker-Ökosystems. Docker Engine kann aktuell auf Linux, macOS und Windows installiert werden, wobei die Container-Technologie selbst auf Linux basiert und macOS und Windows in den aktuellsten Versionen Linux mit den entsprechenden Bordmitteln virtualisieren. Für andere Betriebssysteme sowie für ältere Versionen von macOS und Windows gibt es jeweils die Möglichkeit, den Docker Daemon in einer virtuellen Linux-Maschine zu betreiben (zum Beispiel mit Virtualbox).

Die beiden Komponenten sprechen über eine standardisierte Schnittstelle miteinander. Dabei ist es unwichtig ob sie auf demselben Computer bzw. Server liegen oder über das Internet miteinander sprechen. Man muss das lokale „docker“-Programm einfach über die Umgebungsvariable $DOCKER_HOST entsprechend konfigurieren, wo es seinen Docker-Dienst finden soll. Standardmässig erwartet es den Docker-Dienst auf dem lokalen Unix-Socket /var/run/docker.sock, auf TCP-Port 2375 eines zu konfigurierenden Servers unverschlüsselt oder TCP-Port 2376 mit TLS verschlüsselt.

Docker Inc

Docker Inc ist die Firma hinter Docker, also der Hersteller der Software. Leider ist es im mündlichen Gespräch nicht immer einfach zu unterscheiden wenn man von „Docker macht …“ spricht.

Dockerfile

Das Dockerfile ist eine Textdatei, meistens zusammen mit dem Programmcode im Versionskontrollsystem, welche alle benötigten Befehle enthält um eine Umgebung zu erstellen in welcher der Programmcode laufen kann. Je nach Applikation und Programmiersprache installiert es also einen Applikationsserver, alle benötigten Pakete, Module und Bibliotheken. Meistens fängt man nicht mit einer „leeren“ Umgebung an, sondern nutzt eine von einer verlässlichen Firma gepflegte Basis (dazu gleich mehr). Auf diese Basis müssen dann nur noch die applikationsspezifischen Pakete, Module und Bibliotheken installiert. Alle dafür benötigten Schritte sind im Dockerfile aufgelistet und somit auch gleich für das ganze Team dokumentiert. Ausserdem lassen sie sich dadurch auch sehr einfach automatisieren.

Ebenfalls im Dockerfile steht, welche Dateien der Applikation in den Container übernommen werden sollen, wie der genaue Befehl für die Applikation lautet, auf welchem Port die Applikation dann erreichbar ist und in welchen Verzeichnissen innerhalb des Containers die Applikation ihre Benutzerdaten ablegt (die sogenannten Volumes).

Docker Inc veröffentlicht auch eine Dokumentation was man beim Erstellen des Dockerfiles alles beachten soll.

Ein grundlegendes Muster der Zwölf-Faktoren-Methode und der Container-Welt ist, dass die Konfiguration, also alles was sich zwischen zwei verschiedenen Deploys (Staging, Produktion, Entwicklungsumgebungen, usw.) ändert, in Umgebungsvariablen (Environment Variables) der Applikation übergeben werden sollen. Dazu gehören Ort und Zugangsdaten für Backend-Services (Datenbanken, Caches, S3-Storage, etc.), externe APIs, etc. Wenn die Applikation dies selbst nicht unterstützt, muss das Dockerfile ein Start-Skript erstellen welches dann zur Laufzeit die Daten in den Umgebungsvariablen der Applikation übergibt und sie startet.

Das Dockerfile ist also die Anleitung für die Build-Phase des „Build, Release, Run“-Patterns.

Docker Image

Ein Image ist das Ergebnis wenn ein Dockerfile ausgeführt wurde. Es enthält also die Applikation in einer bestimmten Version und alle für das Ausführen benötigten Komponenten, also ein Release. Das Docker Image kann von der Docker Engine ausgeführt werden und stellt dann die Applikation unter einem bestimmten Port (z.B. TCP Port 80 für HTTP) zur Verfügung. Nur die im Dockerfile definierten Volumes mit Benutzerdaten werden persistent gespeichert und stehen nach einem Neustart oder Update weiterhin zur Verfügung, der Rest des Container-Inhaltes wird verworfen gemäss dem Faktor des Einweggebrauches der Zwölf-Faktoren-Methode (12 Factor App).

Docker Registry

Die Registry speichert die fertigen Images und stellt sie zum Download auf den/die Server zur Verfügung, auf denen sie ausgeführt werden sollen. Docker Inc betreibt eine öffentliche Registry unter https://hub.docker.com/ (auch „Docker Hub“ genannt) welche auch für die Verteilung der öffentlichen Basis-Images verwendet wird. Die Verwendung des Docker Hubs ist kostenlos, dafür sind aber auch alle Daten öffentlich. Für Open Source also kein Problem. Für Applikationen die nicht öffentlich sein sollen braucht es also eine private Registry zur Software-Verteilung. Zum Glück ist eine private Registry kostenlos unter https://hub.docker.com/_/registry/ erhältlich – natürlich läuft sie ebenfalls in einem Docker-Container.

Ganz neu und aktuell noch im Beta-Stadium befindet sich der Docker-Store https://store.docker.com/, welcher wohl irgendwann den Docker Hub ablösen wird.

Docker Machine

Docker Machine ist ein Programm welches entweder auf dem lokalen Computer (mittels Virtualbox) oder in einer Cloud (Liste der unterstützten Cloud-Provider) einen virtuellen Server erstellt und startet um darauf Container auszuführen. Sehr praktisch wenn man Docker nicht nativ auf dem lokalen Computer ausführen kann (z.B. unter Windows) oder der/die Container mehr Ressourcen benötigt als lokal verfügbar sind. Die erstellten virtuellen Server sind aber nur für temporäre Experimente gedacht: sie werden weder überwacht, neu gestartet, mit Backup gesichert oder aktualisiert. Auch ist der virtuelle Server nur auf dem lokalen Computer für den Benutzer sinnvoll nutzbar der ihn erstellt hat: das Programm sichert die Kommunikation mit dem mini-Server mit Schlüsseln ab die nur auf dem lokalen Computer gespeichert werden und startet beim nächsten Verbinden alle Container die bisher liefen ab.

Docker Compose

Im einfachsten Fall besteht eine Applikation nur aus einem Prozess/Container, oft benötigt eine Applikation gemäss der Microservice-Architektur und dem Konzept der Nebenläufigkeit in der Zwölf-Faktoren-Methode einen weiteren Service als Backend, zum Beispiel eine Datenbank oder einen Cache, der wiederum in einem separaten Container läuft. Für viele Standardapplikationen gibt es bereits fertige Docker Images z.B. vom Docker Hub welche durch den Hersteller oder die Community gepflegt werden.

Docker Compose besteht wiederum aus dem Programm „docker-compose“ und der Konfigurationsdatei docker-compose.yml (normalerweise in der Versionsverwaltung der Applikation, neben dem Dockerfile, damit auch da alles am selben Ort ist) in welcher die Services, Volumes und Netzwerke definiert werden welche zusammen gestartet, miteinander kommunizieren und einen oder mehrere Services verfügbar machen sollen.

Die Services in der Konfiguration referenzieren im einfachsten Fall entweder die aktuelle Applikation gemäss Dockerfile oder aber „fertige Images“ (standardmässig vom Docker Hub) und welche Services mit welchem anderen Service (über die in den Dockerfiles definierten Ports) kommunizieren sollen, zum Beispiel die aktuelle Applikation mit dem Datenbank-Container. Ebenfalls müssen die Namen und Ports der benutzten Services als Konfiguration in Umgebungsvariablen der Applikationscontainer definiert werden, zum Beispiel DATENBANK=“mysql:3306″ wenn der Applikationscontainer den Ort der Datenbank in der Variable „$DATENBANK“ erwartet und der MySQL-Service im docker-compose.yml „mysql“ genannt wird und unter dem Port 3306 (MySQL-Standardport) verfügbar ist. Der Befehl „docker-compose up“ startet dann alle Services in der gemäss den Abhängigkeiten definierten Reihenfolge und ermöglicht den Container miteinander zu kommunizieren.

Docker Swarm

Ein Docker Swarm („Schwarm“, also Gruppe) besteht aus mehreren zusammengeschalteten Docker Engines (bzw. Docker-Diensten dockerd, auch Nodes genannt), welche gemeinsam unter „einer zentralen Docker API“ für den Benutzer bzw. das Programm „docker“ erreichbar ist. Dabei ist ein Node der „master“ der die Anfragen des Benutzers entgegennimmt, die Container auf den anderen Swarm Nodes startet und sich um die Kommunikation von/zu den Containern auf den verschiedenen Nodes kümmert.

Swarm ist eine relativ neue Komponente im Docker-Ökosystem und wurde erst Mitte 2016 veröffentlicht. Entsprechend ist der Funktionsumfang noch beschränkt: ein Swarm ist zum Beispiel noch nicht mandantenfähig, alle Services – egal von welchem Benutzer – müssen also eindeutige Namen haben und sind auch untereinander nicht abgeschottet. Entsprechend wird empfohlen für Testing und Produktion separate Swarms zu betreiben.

Vergleich mit Kubernetes

Kubernetes ist eine Alternative zu Docker Compose und Docker Swarm und unterstützt durch die längere Erfahrung z.B. Mandantenfähigkeit und wird gerade für grössere Umgebungen lieber verwendet, zum Beispiel für die Schweizer Container Plattform APPUiO. Um die Orchestrierung mehrerer Container mittels Docker Compose zu übernehmen gibt es das Programm Kompose, dazu werden wir später noch einen ausführlicheren Blogpost schreiben.

Weitere Informationen

Möchtest du weitere Informationen zu Docker erhalten oder eine Offerte anfordern? Bitte nimm Kontakt mit mir auf: