

Docker erfreut sich unter Entwicklern einer immer größeren Beliebtheit. Doch was genau ist Docker und wie hilft es Entwicklern dabei Ihren Code zu „verschiffen”?
Diese Ausarbeitung ist im Rahmen der Vorlesung zum Thema „Betriebssysteme” entstanden. Sie soll einen kurzen Einblick in das Thema Docker bieten, so dass Sie am Ende dieses Artikels die Grundlagen und den Nutzen von Containern verstanden haben.
Docker ist eine Art virtuelle Maschine auf welcher man entkoppelt vom eigentlichen Host Betriebssystem Anwendungen laufen lassen kann. Aufgrund seiner Architektur (siehe Abbildung 1) benötigt Docker allerdings deutlich weniger Ressourcen als eine virtuelle Maschine. 1

Jede Anwendung wird nach dem Entwickeln durch Docker in einem so genannten Image gebündelt. Ein Image kann dann von einer Docker Engine heruntergeladen und in einem Container ausgeführt werden. Diese Architektur garantiert eine stets gleiche Anwendungsumgebung, egal auf welchem Host Betriebssysteme der Container ausgeführt wird.
Docker kann man sich von der offiziellen Docker Webseite herunterladen und installieren.
Ein Docker Image durchläuft grundlegend zwei Phasen. Die Build- und die Run-Phase. Dies sind keine offiziellen Bezeichnungen, dienen meines Erachtens aber dem besseren Verständnis. Siehe Abbildung 2.

Ein Image kann jegliche Art von Software Prozess beinhalten. Um ein Image zu generieren, ist ein Dockerfile notwenig. Dies ist eine Datei welche im Root des Projektes platziert wird und für Docker relevante Informationen beinhaltet. Man kann sich diese Datei wie eine Art Bauanleitung vorstellen.
Nachfolgendes Beispiel zeigt exemplarisch die Erstellung eines einfachen NodeJS Webservers, der lokal oder extern auf einem Server in der Docker Engine ausgeführt werden kann.
/ Dockerfile
# 3.1 FROM - Base Image
FROM node:15.6
# 3.2 WORKDIR - Das Arbeitsverzeichnis
WORKDIR /usr/src/app
# 3.3 COPY - Dateien kopieren
COPY . .
# 3.4 EXPOSE - Port Freigaben
EXPOSE 8080
# 3.5 RUN und CMD
RUN npm install
CMD ["node", "server.js"]
/ package.json
Diese Datei wird von dem Node Package Manager npm verwendet, um Informationen für das Projekt zu speichern.
Der Node Package Manager ist eine Paketverwaltung welche es erlaubt, von anderen Personen erstellte Bibliotheken zu installieren und in NodeJS zu verwenden.
{
"name": "Docker Web Server",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.17.1"
}
}
/ server.js
Diese Datei beinhaltet den Server Code.
// Importiere die Server Bibliothek
const app = require('express')()
// Definiere den Port auf welchem der Server laufen soll
const PORT = 8080
// Definierer die Routen des Web Servers
app.get('/', (req, res) => {
res.send({ message: 'Hallo Welt!' })
})
// Startet den Server
app.listen(PORT, () =>
console.log(`Der Server wurde gestartet.`)
)
Jedes Dockerfile startet mit einem Base Image. Dieses legt eine grundlegende Umgebung für das eigene Docker Image fest. Mit dem FROM Schlüsselwort und einem darauf folgendem Image-Namen wird Docker aufgefordert, den darauf folgenden Code in diesem Image auszuführen. Ein Base Image kann man sich entweder aus einem Repository oder aus der Docker Hub, einer Community für Docker Images herunterladen.
FROM <image>:<tag>
In unserem Dockerfile haben wir die neuste Version des offiziellen NodeJS Images von Docker Hub verwendet.

Einen Tag (Deutsch Etikett) verwendet man, um ein Image auf eine bestimmte Release Version festzusetzen. Dies verhindert, dass das Programm unter einer neueren Version möglicherweise nicht länger auszuführen ist. Die unterschiedlichen Release Tags findet man auf der Docker Hub unter der Beschreibung des jeweiligen Image. 2
Da die JavaScript Entwickler sehr großen Fokus auf Backwards Compatibility legen 3 ist dies für unser NodeJS Image nicht unbedingt notwendig. Wird kein Tag angegeben, fällt Docker auf das Release mit dem Namen latest zurück. 4
Wie der Unix Befehl cd, navigiert man mit WORKDIR in das gewünschte Verzeichnis. Nachfolgende Docker Befehle wirken sich dann auf das angegebene Verzeichnis aus. 5
Mit dem COPY Befehl werden Daten und Verzeichnisse aus dem aktuellen Projekt in das zu erstellende Docker Image kopiert. 6
Die Quelldateien (src) werden relativ zu dem Verzeichnis ausgewählt aus welchem das Dockerfile stammt. Das Zielverzeichnis (dest) ist relativ zu dem zuvor definierten Arbeitsverzeichnis WORKDIR.
COPY <src>... <dest>
Mit COPY . . kopiert man Dateien aus dem Projekt in das Docker Image.
Damit der Server auch erreichbar ist, muss man dem Docker Image mitteilen, dass der Container eine Portfreigabe benötigt.
EXPOSE <port> [<port>/<protocol>...]
In der NodeJS Anwendung wurde für den Server der Port 8080 definiert.
Sowohl RUN als auch CMD führen einen beliebigen, in dem Image verfügbaren Systemaufruf aus. Der Unterschied zwischen den beiden Befehlen ist, dass RUN während der Build-Phase und CMD als Einstiegspunkt für das fertige Image gilt.
Wird unser Server Image gebaut, so werden mit dem npm install Befehl sämtliche Pakete installiert, die in der package.json Datei vorausgesetzt wurden. Ist dies geschehen, sind die heruntergeladenen Pakete fester Bestandteil des fertigen Image.
In jedem Dockerfile darf es nur einen CMD Befehl geben. Dieser legt fest, was tatsächlich ausgeführt werden soll. Man spricht nun nicht länger von einem Image, sondern von einem Container.
Siehe Abbildung 2: Docker Phasen.
Nachdem das Image mit docker build -t webserver . gebündelt wurde, kann das Image ausgeführt werden.
Verfügbare Images anzeigen
Einen Überblick über alle zur Verfügung stehenden Images erhält man mit dem Befehl docker images oder über die Docker Desktop UI. Dies gibt eine Tabelle mit heruntergeladenen / vorhandenen Docker Abbildern zurück.

Um ein Image auszuführen verwendet man den docker run <image> Befehl. Dieser erstellt einen neuen Container basierend auf dem gegebenen Image. Ist das Image nicht vorhanden ist aber unter Docker Hub auffindbar, so wird das Image zunächst heruntergeladen bevor es ausgeführt wird.
Mit nachfolgendem Befehl wird das Image unter Verwendung des Containernamens und Port ausgeführt.
docker run --name mein_express_server -p 80:8080 webserver
Öffnen wir nun die Adresse http://localhost in dem Browser unserer Wahl sehen wir:
Voilà der Server läuft 🥳

Die Ausarbeitung soll einen Einblick darüber vermitteln, was Docker ist und wie es verwendet werden kann. Es umfasst selbstverständlich noch weiter Funktionalitäten. Die nachfolgende Tabelle zeigt die wichtigsten Befehle und veranschaulicht die Programmvielfalt.
| Befehl | Beschreibung |
|---|
Cheat Sheet gehostet unter jsonbin.io: https://api.jsonbin.io/b/60099a4d97391458068818c6