1. Docker

_images/docker-logo.png

1.1. Einführung

1.1.1. Was ist Docker?

Docker ist eine Open Source Plattform zum Entwickeln, Versenden und Ausführen von Anwendungen. Mit Docker können Anwendungen von der Infrastruktur getrennt werden, um Software schnell bereitzustellen. Docker bietet die Möglichkeit, eine Anwendung in einer lose isolierten Umgebung zu packen und auszuführen, die als Container bezeichnet wird.

1.1.2. Docker Architektur

Docker benutzt eine Client-Server Architektur. Der Docker Client kommuniziert mit dem Docker Daemon, welcher das Erstellen, Ausführen und Verteilen der Docker Container übernimmt. Der Docker Client und Daemon können sowohl auf dem gleichen Zielsystem laufen, als auch auf unterschiedlichen.

_images/docker-architecture.svg

1.1.3. Docker Registry

Eine Docker Registry speichert Docker Images. Docker Hub ist eine öffentliche Registry, welche von jedem verwendet werden kann und als Standard für die Image-Suche gesetzt ist. Auf Docker Hub gibt es bereits zahlreiche vorkonfigurierte Images für häufig verwendete Setups, wie etwa:

  • Nginx

  • MongoDB

  • Alpine Linux

  • Node.js

  • Redis

  • Python

1.2. Die wichtigsten Befehle

1.2.1. Image Verwaltung

$ docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
linuxserver/plex               latest              21b26352f33d        12 hours ago        690MB
linuxserver/tautulli           latest              986c34547cc6        4 days ago          117MB
netdata/netdata                latest              323be1e05bba        8 days ago          325MB
linuxserver/nextcloud          latest              fab91a6702b8        9 days ago          399MB
itzg/minecraft-server          latest              106592c794e4        9 days ago          396MB
linuxserver/mariadb            latest              ef4803049577        10 days ago         350MB
jlesage/nginx-proxy-manager    latest              36d82e1382b8        2 weeks ago         163MB
portainer/portainer            latest              580c0e4e98b0        2 weeks ago         79.1MB
jlesage/jdownloader-2          latest              e8035ce15008        3 weeks ago         224MB
homeassistant/home-assistant   latest              d1ac3982d662        3 weeks ago         1.08GB
mitchellriley/streetmerchant   latest              21f207898bff        2 months ago        561MB
dperson/openvpn-client         latest              40876b9dd828        9 months ago        20MB

docker images listet alle installierten Images auf.

$ docker pull <image>

Mit docker pull <image> wird das angegebene Image heruntergeladen und direkt installiert.

$ docker push <image>

Mit docker push <image> wird das angegebene Image auf die Registry hochgeladen und kann von anderenEntwicklern benutzt werden.

$ docker build <path>

Mit docker push <path> wird anhand von dem angegebenen Dockerfile mit speziellen Befehlen ein neues Image erstellt.

$ docker commit <image>

Mit docker commit <image> wird eine neue Version für ein Image erstellt.

1.2.2. Container Verwaltung

$ docker container run <name>

Mit docker container run <name> wird ein Container gestartet. Mit den Flags -it wird eine interaktive Kommandozeile geöffnet, mit der man im Container arbeiten kann.

$ docker container stop <name>

Mit docker container stop <name> wird ein Container gestoppt.

$ docker container rm <name>

Mit docker container rm <name> wird ein Container gelöscht.

1.3. Netzwerke

Docker Services können untereinander und mit nicht Docker-Anwendungen kommunizieren. Docker-Container und -Dienste müssen nicht einmal wissen, dass sie auf Docker bereitgestellt werden oder ob ihre Peers auch Docker-Workloads sind oder nicht.

1.3.1. Bridge

Der Standard-Netzwerktreiber. Wenn Sie keinen Treiber angeben, ist dies der Netzwerktyp, den Sie erstellen. Brückennetzwerke werden normalerweise verwendet, wenn Ihre Anwendungen in eigenständigen Containern ausgeführt werden, die kommunizieren müssen. Siehe Brückennetzwerke.

1.3.2. Host

Entfernen Sie bei eigenständigen Containern die Netzwerkisolation zwischen dem Container und dem Docker-Host um direkt das Host Netzwerk zu verwenden.

1.3.3. Overlay

Overlay-Netzwerke verbinden mehrere Docker-Daemons miteinander und ermöglichen es Swarm-Diensten, miteinander zu kommunizieren. Sie können auch Overlay-Netzwerke verwenden, um die Kommunikation zwischen einem Schwarmdienst und einem eigenständigen Container, oder zwischen zwei eigenständigen Containern auf verschiedenen Docker-Daemons zu erleichtern. Diese Strategie macht das Routing auf Betriebssystemebene zwischen diesen Containern überflüssig.

1.3.4. Macvlan

In Macvlan-Netzwerken können Sie einem Container eine MAC-Adresse zuweisen, sodass er als physisches Gerät in Ihrem Netzwerk angezeigt wird. Der Docker-Dämon leitet den Datenverkehr anhand seiner MAC-Adressen an Container weiter. Die Verwendung des Macvlan-Treibers ist manchmal die beste Wahl, wenn es sich um ältere Anwendungen handelt, die voraussichtlich direkt mit dem physischen Netzwerk verbunden sind, anstatt über den Networkstack des Docker-Hosts geleitet zu werden.

1.3.5. None

Für diesen Container werden alle Netzwerke deaktiviert. Dies wird normalerweise in Verbindung mit einem benutzerdefinierten Netzwerktreiber verwendet. none ist nicht für Swarm verfügbar.

_images/docker-networks.jpg

1.4. Virtualisierung

1.4.1. Docker

Die Virtualisierung von Docker basiert auf einer Containertechnik. Hierbei handelt es sich nicht um eine klassischen Hypervisor-Virtualisierung. Docker ist eine Anwendungsvisualisierung auf Betriebssytemebene. Hierbei wird angestrebt, dass man mehrere Anwendungen auf derselben Hardware voneinander abgekapselt ausführen kann. Der Vorteil von Docker gegenüber klassischer Virtualisierungsmethoden liegt darin, dass nur ein Kernel auf dem Hostsystem läuft. Es wird auf den Dockerdeamon zurückgegriffen, der die einzelnen Container und die Containerprozesse mithilfe des Hostkernels verwaltet. Dadurch fallen Hypervisor und Emulationsschichten aus.

1.4.2. Typ 1 Hypervisor (native)

Hier wird der Hypervisor direkt auf der Hardware aufgesetzt. Dadurch werden keine vorherigen OS-Installationen benötigt.

1.4.3. Typ 2 Hypervisor (hosted)

Bei diesem Typ wird ein vollwertiges Betriebssystem benötigt auf dem Hostsystem benötigt. Der Hypervisor wird auf dem Betriebssystem des Hostsystems installiert.

1.4.4. Darstellung

_images/docker-visualisierungstypen.png

1.5. Images & Container

Ein Image ist eine Vorlage mit Instruktionen für das Erstellen eines Docker Containers. Images können aufeinander aufgebaut werden, d.h. das ein Image ein anderes Image als Grundlage benutzt.

1.6. Dockerfile

– Docker kann automatisch Images aus Instruktionen in einer sogenannten Dockerfile erstellen. Dieses Dockerfile ist lediglich ein Text Dokument, welches alle Befehle beinhaltet, die einda Benutzer ausführen würde, um das gewünschte Image zu erstellen. Mithilfe von docker build kann das Dockerfile dann ausgeführt werden.

1.7. Praxisbeispiel

Als Beispiel wird eine Django/PostgreSQL Anwendung erläutert.

1.7.1. Projektkomponenten definieren

Zunächst werden die Projektkomponenten definiert. Hierzu wird ein Projektordner mit dem Namen docker-django erstellt. In diesem Ordner wird nun ein Dockerfile mit folgendem Inhalt angelegt.

FROM python:3.9.4-buster
ENV PYTHONUNBUFFERED=1
WORKDIR /app

COPY requirements.txt ./

RUN pip install --no-cache-dir -r requirements.txt
CMD python manage.py runserver 0.0.0.0:8000

Anschließend erstellen wir die requirements.txt welche alle nötigen Python Pakete enthält. In unserem Fall:

Django>=3.0,<4.0
psycopg2-binary>=2.8

Nun erstellen wir die docker-compose.yaml. Diese Datei beschreibt die Dienste aus welchen unsere Anwendung besteht. In diesem Fall der Django Webserver und die PostgreSQL Datenbank. Die Konfigurationsdatei beschreibt ebenfalls welche Docker Images diese Dienste benutzen und wie diese miteinander verbunden sind. Letztlich wird in der docker-compose.yaml beschrieben welche Ports von den jeweiligen Diensten sichtbar sind. Der Inhalt der Konfigurationsdatei entspricht Folgendem:

version: "3.9"

services:
    db:
        image: postgres
        volumes:
            - ./data/db:/var/lib/postgresql/data
        environment:
        - POSTGRES_DB=postgres
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=postgres
    web:
        build: .
        volumes:
        - .:/app
        ports:
        - "8000:8000"
        depends_on:
        - db
        restart: always

1.7.2. Django Projekt erstellen

Um ein Django Projekt zu erstellen führen wir folgenden Befehl aus:

docker-compose run web django-admin startproject composeexample .

1.7.3. Datenbank anschließen

Um Django den richtigen Datenbank Adapter mitzuteilen muss dieser unter composeexample/settins.py beschrieben werden. Hierzu den Standardeintrag für DATABASES durch Folgenden ersetzen:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
    }
}

Letzlich wird docker-compose up ausgeführt. Dies erstellt alle nötigen Image und startet die relevanten Container. Unter http://localhost:8000 sollte nun die Django Welcome Page sichtbar sein:

_images/docker-django-welcome-page.png