Docker wird genutzt um wie Vagrant das Problem „it works on my machine“ zu beseitigen. Jedoch muss dabei keine virtuelle Maschine erstellt werden und die Zeit für das hochfahren einer Entwicklungsinstanz wird minimiert.

Der grosses Plus von Docker ist das keine virutelle Maschine für jeden Service aufgesetzt werden muss. Es werden sogenannte Container direkt auf der Docker-Runtime laufen gelassen. Unter dem Begriff Container versteht man eine Einheit,  welche einen Service auf der Docker Platform laufen lässt. Die Docker-Runtime teilt seine Grund-Layer mit all seinen Containern, welche je ein virtuelles Filesystem besitzen. Auf diesen auf diesen Containern ist normalerweise eine stark reduzierte form eines Betriebssystem aufgesetzt. Die einzelnen Container sind unabhängig von einander, können jedoch miteinander kommunizieren.

Dadurch besitzt man eine Abkoppelung der einzelnen Systeme, muss jedoch keine eigene virtuelle Maschinen, mit hoher Ressourcen nachfrage, aufsetzten. Doch wenn nun die Maschine auf der die Docker-Runtime ist nicht mehr funktioniert,  funktionieren alle Container und ihre Services darauf nicht mehr. Aus diesem Grund gibt es ein weiteres Tool von Docker welches sich Swarm nennt. Dieses Tool ermöglicht es Container über mehrer Maschinen laufen zu lassen.

Ein weiterer Punkt für Docker ist das Dockerfile. Dort wird beschreiben, was auf dem Container installiert wird, was für Dateien auf den Container kopiert werden und was für ein Command ausführt wird. Im Grunde beschreibt er einen Service. Das wohl beste an diesen Dockerfiles ist, das sie ein anderes Dockerfile als Vorlage benutzen können. So kann ich ein Dockerfile nehmen und nach meinen Vorgaben ergänzen. Es gibt ein öffentliches Repository genannt Docker Hub. Hier werden viele vordefinierte Images angeboten meist von den Herstellern der Software selbst. Die Dockerfile müssen zu Images gebuildet werden, damit sie in Docker laufen gelassen werden können.

Zusammengefasst die Vorteile von Docker:

  • versionierte Konfiguration (Dockerfile im Git)
  • Portabilität
  • Skalierbarkeit (Swarm)
  • Behebung von „it works on my machine“
  • schnelles aufstarten einer komplexen Entwicklungsumgebung

Die Nachteile:

  • Mehr zeit für Setup
  • Docker Probleme

Hierbei muss abgewogen werden ob es sich der Aufwand lohnt um Docker zu benutzen bzw. ob sich Docker in den Entwicklungsprozess integrieren kann. Für kleine Projekte ist es sicher fraglich Docker zu verwenden, wenn auch anders geht. Benutz man jedoch eine Microservice-Architektur, lohnt sich der Einsatz von Docker. Dies gilt auch wenn man viele verschieden Services wie Redis oder Elasticsearch im Gebraucht hat. Docker ist ausserdem sehr beliebt um seine Applikation in einer Cloud-Infrastruktur aufzusetzen, da es die gleichen Konfigurationsdateien benutzt, welche auch für die lokale Entwicklung gebraucht werden.

Praktisches Beispiel

Setup

Um Docker zu nutzen muss man zuerst die entsprechende Laufzeitumgebung installieren, welche für die drei grossen Systeme vorhanden ist.

Container einrichten

Um nun einen der oben genannten Container zu starten, braucht Docker eine Vorlage. Diese Vorlage ist ein Dockerfile. Als Beispiel nehmen wir eine Web-App welche mehrere Komponenten benötigt. Sie besitzt einen Node-Server, der eine React Seite liefert. Diese React-Seite ruft Daten von einer Flask API ab, welche wiederum ihre Daten in einem Redis-Server speichert.

Der React-Server wurde mit Kyt generiert und kann mit dem Command ’npm run start‘ auf dem Port 3000 laufengelassen werden. Das Dockerfile sieht folgend aus:

Mit dem „From“ Keyword wird beschrieben von welchem Dockerfile unsere abgeleitet werden soll. Das heisst wir haben nun ein Dockerifle mit Node installiert und mit ADD kopieren wir unseren Frontend Code auf den Container. Danach installieren wie die Dependencies und lassen den Server auf dem Port 3000 laufen.

Das Dockerfile für den Python Server geht folgendermassen:

Ähnlich wie beim Dockerfile des React-Server installieren wir die Dependencies und lassen das Script laufen.

 

Schlussendlich wird ein Nginx Webserver als Reverse-Proxy benutz und bekommt folgendes Dockerfile:

Hier kopieren wir die Nginx-Konfiguration welche in das Nginx-Verzeichnis kopiert wird. Die Konfiguration sieht folgend aus:

Wir leiten den Traffic auf die URL „https://react:3000“ um. Die Url „react“ ist lokal auf der Docker-Runtime registriert und wird später genauer erklärt.

Wir wollen diese drei Docker Container gemeinsam builden und starten. Dafür gibt es den „docker-compose“ Command. Dafür wird eine Datei „docker-compose.yml“ erstellt. In dieser Datei wird beschrieben wie die drei Dockerfiles zusammen arbeiten und welche Port umgeleitet werden sollen.

Hier beschreiben wir die vier Services. Wir haben das Frontend mit React, Backend mit Python, den Nginx Proxy und  einen Redis Server. Alle werden miteinander gestartet. Bei dem Nginx-Service wird der Port 80 auf den Port 80 des Containers umgeleitet. Ausserdem sagen wir mit „depends_on“ das zuerst der React Server gestartet werden muss da sonst der Reverse Proxy gar nichts weiterleiten kann. Mit den „Volumes“ wird bestimmt welche Directory kopiert werden soll und dabei wird auch automatisch auf Filechanges geachtet und neu kopiert.

Oben in der Nginx-Konfiguration haben wir in der Url „http://react:3000“ angegeben. Dies ist möglich da Docker einen eigenen Network manager hat und den Namen des Services als Hostname benutzt.

Container starten

Die Container Umgebung kann mit dem Command „docker-compose –build“ gestartet werden. Das Argument „–build“ wird nur das erstemal gebraucht. Dies teil docker-compose mit, das zuerst die Docker Images gebuildet werden müssen. Danach werden die Container gestartet und die Seite kann unter dem Localhost geöffnet werden.