In den letzten Jahren hat sich Docker zum quasi Standard für Microserviceumgebungen herangemausert. Es ermöglicht jedem Service in einer eigenen Umgebung zu laufen ohne für jeden Service ein komplettes Betriebssystem installieren zu müssen. Warum ist Docker so erfolgreich? Docker Container sind besser als klassische Virtualisierungen weil sie …

  • deutlich schlanker sind
  • nicht zwangsläufig eigene IP-Adresse im Netzwerk brauchen
  • von Haus aus IaC (Infrastrcuture As Code) bereitstellen
  • schnell redeployed werden können
  • mit Kubernetes zusammen riesige, skalierende Servicenetzwerke anbieten können

In diesem Tutorial lernst du was Docker ist und wie du dein erstes Docker Image erzeugst und ausführst.

Was ist Docker

Docker ist eine Technologie zur Virtualisierung von Services. Bei klassischer Virtualisierung wird eine ganze Linux bzw. Windows Installation bereitgestellt. Das hat zur Folge, dass für jede Instanz oft mehrere Gigabyte an Speicher benötigt werden und die Installation entsprechend lange dauert. Docker geht einen anderen Weg!

Container System

Um einen Service auf Docker laufen zu lassen brauchst du zwei Dinge: - ein Hostsystem

  • ein Docker Image

Das Hostsystem kannst du auf allen gängigen Betriebssystemen installieren (Klick). Die meisten Docker Container benötigen eine Linux Umgebung. Deswegen solltest du bei der Windows und der Mac OS Installation darauf achten Linux Container Ausführung zu aktivieren. Das Docker Image beschreibt, wie sich der Container beim Zeitpunkt des Hochfahrens verhalten soll. Du kannst entweder ein fertiges Image aus dem Internet laden oder dein eigenes verwenden. Die meisten kostenlosen Images findest du übrigens auf Docker Hub. In diesem Beitrag lernst du zusätzlich wie du dein erstes eigenes Docker Image erzeugst.

Geteiltes Betriebssystem

Auf dem Dockerhostsystem werden die Betriebssystemdateien allen darauf installierten Docker Containern als geteilte Ressourcen bereitgestellt. Das hat den Vorteil, dass diese nur einmal vorhanden sein müssen. Anschließend wird - ähnlich wie bei klassischen Virtualisierungshostsystemen - den installierten Services auf den einzelnen Containern vorgegaukelt der einzige installierte Service zu sein.

Skizze des Dockerprinzips von App bis Infrastruktur

Port Management

Jeder Service Container bietet seinen Service meist auf einem oder mehreren Ports an. Das Dockerhostsystem hat jetzt die Möglichkeit diese Ports nach außen erreichbar zu machen. Für andere Computer im Netzwerk sieht es dann so aus, als würden diese Services auf dem Dockerhostsystem laufen (was sie praktisch ja auch tun). Damit es keine Portüberschneidungen gibt, kann das Dockerhostsystem selbst entscheiden auf welchen Port der jeweilige Service des Containers angeboten wird.

Persistente Speicher (Volumes)

Sobald ein Docker Container neu startet wird der Container mithilfe des Images von Grund auf neu installiert. Deswegen sind gespeicherte Dateien immer nur temporär. Wenn du persistente Daten verwenden möchtest, musst du das explizit angeben. Der gängigste Weg ist ein Volume bereitzustellen. Dieses Volume muss beim Start des Containers angegeben werden. Dafür kannst du zum Beispiel einen Ordner in deinem Betriebssystem nehmen. Volumes können übrigens auch zwischen mehreren Containern geteilt werden. Dadurch können die Container Dateien austauschen.

Wie du ein Docker Image erstellst

Ist Docker installiert, geht es ans Eingemachte. Prinzipiell ist es egal, von welchem System du deine Docker Container Images baust. Theoretisch sind die Container auf allen anderen Systemen lauffähig. Üblicherweise werden Linux Container verwendet. Für manche Anwendungen sind aber auch Windows Container sinnvoll. Etwa bei MS SQL Datenbankcontainern. Um ein Docker Image zu erstellen, benötigst du in jedem Fall eine Dockerfile. In dieser Datei wird das Verhalten des Containers definiert. Der Inhalt der Dockerfile listet die Befehle in Ausführreihenfolge auf, die zum Installieren des Containers benötigt werden. Hier die möglichen Befehle.

Befehl Beschreibung
FROM Spezifiziert das Basisimage (wie Vererbung). Dieses MUSS vorhanden sein
LABEL Zusätzliche Metadaten, etwa für Infos über die Maintainer
ENV setzt eine persistente Umgebungsvariable
RUN führt ein (Shell-) Kommando aus (und erstellt ein Image Layer)… Du kannst es benutzen, um Pakete in deinen Container zu installieren
COPY Kopiert Dateien oder Ordner von deinem Buildsystem in das Image
ADD Funktioniert ähnlich wie COPY. Entpackt allerdings .tar Dateien und lädt Links herunter
CMD Das Hauptkommando mit Argumenten für diesen Container. Es darf jedoch nur einen CMD Befehl pro Dockerfile geben. Parameter können übrigens überschrieben werden.
WORKDIR Setzt das Arbeitsverzeichnis für die folgenden Befehle und ist daher vergleichbar mit dem cd Kommando in Linux & Windows CLI’s
ARG Definiert eine Variable, welche du beim Bauen mitgeben kannst
ENTRYPOINT Gibt Kommandos und Argumente an die beim Ausführen mitgegeben werden können. Argumente sind dabei persistent.
EXPOSE Gibt einen Port frei
VOLUME Erstellt einen Mountpunkt um darüber auf persistente Daten zugreifen zu können

Container

Neue Docker Container müssen auf anderen, bereits existierenden Container Images aufbauen und ergänzen diese um zusätzliche Software. Folglich musst du in der Dockerfile mit dem FROM Befehl ein Basisimage angeben. Hier ein paar der populärsten Container Images die du verwenden kannst:

container Beschreibung
scratch Kleinstmöglichstes Image
Alpine Alpine Linux Distribution
busybox Busybox Linux Distribution
Centos Centos Linux Distribution
Debian Debian Linux Distribution
Ubuntu Ubuntu Linux Distribution
Postgres Postgres Datenbank (Objekt-relationales Datenbankensystem)
Redis Redis Datenbank (key-value Speicher)
Node Node.js Umgebung (JavaScript basierte Plattform für serverseitige- und Netzwerkapplikationen)
Nginx NGINX Service (Webserver)
Mysql mysql Datenbank (relationales Datenbanksystem)
Mongo MongoDB Datenbank (Binärspeicher mit Funktionen für high availablity und hoher Skalierbarkeit)
Httpd Apache Service (Webserver)
Mariadb MariaDB Datenbank (relationales Datenbanksystem)
Golang Golang Umgebung (Go ist eine beliebte und schnelle Programmiersprache für Serverseitige Anwendungen)
Wordpress Wordpress System (Content Management System für Blogs und ähnlichen Webseiten)

Weitere findest du hier: https://hub.docker.com/search?q=&type=image

Diese vorgefertigten Images bieten oft einen schnellen Start für den eigenen Container. Viele Images werden auch mit unterschiedlichen Distributionen angeboten. So basiert das normale Pythonimage auf Debian. Es gibt aber auch die deutlich kleinere auf Alpine basierende Version (nur 5,6 MB anstatt 114 MB). Diese werden mithilfe von Tags gespeichert. Du wählst sie mit dem Doppelpunkt nach dem Imagenamen.

Dockerfile Beispiel

Erstelle im aktuellen Verzeichnis eine Datei app.py:

print(Hallo Welt!)

und eine Datei dockerfile:

FROM python:3.9-alpine
COPY app.py /app/app.py
CMD python /app/app.py

Baue das Image mit docker build.

docker build . -t hallowelt

Und führe es mit docker run aus.

docker run hallowelt
Hallo Welt!

Was ist eine Docker Container Registry

Dieses Image hast du nur auf deinem Rechner gebaut. Um es anderen Entwicklern bereitzustellen, kannst du es auf Docker Hub oder einer anderen Registry hochladen. Eine Registry ist also ein Service der Docker Images speichert. Docker Hub ist für öffentliche Images gratis. Hier findest du eine Anleitung wie es verwendest. Das Beispiel aus diesem Beitrag habe ich hier hochgeladen. Du kannst es mit folgendem Befehl herunterladen und Ausführen:

docker run quisl/hallowelt:latest

Übrigens: Ich habe hier im Beispiel den latest Tag verwendet. Dies ist eigentlich kein richtiger Tag. Stattdessen nimmt Docker bei latest automatisch die neuste Version des Images.


Konnte ich helfen? Ich freue mich über einen Drink! 💙