BigData

1 Relationale Datenbanken

In der Praxis sind Relationale Datenbankmanagementsysteme immer noch von großer Bedeutung[3].

1.1 Datenbank-Entwurf

Nach Bearbeitung dieses Kapitels können Sie ...

  • ... ein konzeptionelles ER-Modell entwerfen
  • ... ein ER-Modell in ein Relationales Datenmodell überführen
  • ... ein Relationales Datenmodell optimieren
  • ... eine Tabellenstruktur in einer Datenbank anlegen

(Präsentation aus dem Unterricht)

1.1.1 Entwurfs-Phasen

Beim Entwurf von Datenbanken durchläuft man die folgenden Phasen:

Externe Phase
Meist ausgehend von den Attributen des Klassendiagramms werden in der Anforderungsanalyse die zu speichernden Informationen bezogen auf die Anwendung ermittelt.
Konzeptionelle Phase
Der Sachverhalt wird in einem sematischen Modell formalisiert beschrieben. Am Schluss dieser Phase steht ein Entity Relationship Modell[4]. Dieses ER-Modell stellt hauptsächlich die Entitätstypen und deren Beziehungen untereinander mit den entsprechenden Kardinalitäten übersichtlich dar.
Logische Phase
Das semantische Datenmodell wird in ein relationales Datenmodell überführt. Dabei werden die Beziehungen zwischen den Tabellen konkret über Schlüsselfelder bzw. Verknüpfungstabellen realisiert. Anschließend wird das relationale Schema durch Normalisierung optimiert. Außerdem dürfen keine Prozessdaten gespeichert werden.
Physische Phase
Nach Festlegung der Datentypen wird das relationale Schema in einer Datenbank (z.B. mit SQL-Befehlen) angelegt.

1.1.2 Normalformen[5]

Zur Vermeidung von Redundanzen, die zu Anomalien führen können, sollten Datenbanken normalisiert werden.

1. Normalform
Atomare Werte.
2. Normalform
Jedes Nicht-Schlüsselattribut ist vom gesamten Schlüssel abhängig.
3. Normalform
Nicht-Schlüsselattribute sind voneinander unabhängig.

Links zum Nachschlagen

Arbeitsauftrag:

  • Datenbank für Rechnungserstellung:
  1. Erstellen Sie ein Datenbank-Modell in der Chen-Notation, die alle Informationen enthält, um eine Rechnung zu erstellen.
  2. Vergleichen Sie Ihr ER-Modell mit dem Modell an der Tafel, listen Sie die Unterschiede auf und beschreiben Sie die Auswirkungen in der Praxis.
  3. Überführen Sie das ER-Modell zur Rechnungserstellung in ein relationales Datenmodell.
  4. Überprüfen Sie das Datenmodell auf die drei Normalformen.
  • Betriebsabrechnungs-Datenbank:
  • Jeder Kunde hat die Attribute Name und Adresse.
  • Jeder Mechaniker hat die Attribute Name und Ausbildungsstand.
  • Jede Auftragsposition hat die Attribute Beschreibung und AnzahlArbeitseinheiten.
  • Kunden vergeben Aufträge; dabei erfolgt die Vergabe an bestimmtem Tag.
  • Mechaniker bearbeiten Aufträge; manche Aufträge werden von mehreren Mechanikern bearbeitet.
  • Jeder Auftrag besteht aus mindestens einer und maximal beliebig vielen Auftragspositionen.
    Auftragspositionen können zu mehreren Aufträgen gehören.
  • Mechaniker vergeben keine Aufträge.
  1. Definieren Sie ein entsprechendes, konzeptionelles Entity-Relationship Modell.
  2. Überführen Sie das ER-Modell in ein relationales Datenbankmodell. Vergessen Sie nicht alle Primär- und Fremdschlüssel sowie Attribute anzugeben.
  3. Überführen Sie das Modell in die dritte Normalform.
  • Datenbank für die Einkaufsabteilung:
  • ein Einkäufer führt mehrere Bestellungen aus
  • mit jeder Bestellung werden eine oder mehrere Waren zu unterschiedlichen Stückzahlen bestellt
  • eine Ware kann jeweils nur bei einem Hersteller bezogen werden
  • jede Ware wird einer Warengruppe zugeordnet
  • an einem Lagerort können mehrere Waren gelagert werden
  1. Erstellen Sie hierzu das entsprechende ER-Modell in der Chen-Notation.
  2. Überführen Sie das ER-Modell in ein relationales Datenbankmodell in der Dritten Normalform.
  • Datenbank für Online-Schichtplan:
  1. Entwickeln Sie aus dem Klassendiagramm, dem das WebTaxi Lastenheft zu Grunde liegt, für den Online-Schichtplan ein ER-Modell.
  2. Überführen Sie das ER-Modell für den Online-Schichtplan in ein relationales Datenmodell.
  3. Überprüfen Sie das Datenmodell auf die drei Normalformen.

1.2 Vererbungen realisieren

Relationale Datenbanken können keine Vererbungsstrukturen darstellen. Es gibt verschiedene Wege, Vererbungshierarchien objektorientierter Modelle auf Datenbanktabellen abzubilden[6].

1.3 SQL

SQL am Beispiel der verbreiteten MySQL-Datenbank (Präsentation aus dem Unterricht).

Nordwind.png

Für Übungszwecke eignet sich die Nordwind-Datenbank.

Arbeitsauftrag:

  1. Vorbereitung:
    1. Installieren Sie xampp im Hauptverzeichnis auf Ihrem PC.
    2. Rufen Sie C:\xampp\xampp-control.exe auf und starten den Apache-Webserver und die MySQL-Datenbank. Falls der Apache nicht startet, kontrollieren Sie mit netstat -an ob der Port 80 belegt ist. In diesem Fall können Sie in der c:\xampp\apache\conf\httpd.conf über den Eintrag 'Listen' den Port umstellen, z.B. auf 8080.
    3. Speichern Sie das SQL-Skript lokal auf Ihrem PC.
    4. Importieren Sie das Skript mit dem phpMyAdmin, alle erforderlichen Datenbanken und Tabellen mit Daten werden angelegt.
  2. Legen Sie eine leere Datenbank an und überführen Sie das folgende ER-Modell
    er-modell.png
    mit Hilfe von SQL-Befehlen in Tabellen. Legen Sie die entsprechenden Primär- und Fremdschlüssel und alle Verknüpfungen an.
    Dokumentieren Sie alle hierfür notwendigen SQL-Befehle.
  3. Ermitteln Sie die SQL-Befehle für diese Abfragen[1].
    Dokumentieren Sie Ihre Lösungen, hierfür können Sie diese Vorlage verwenden.

Links zum Nachschlagen

Tutorials und Lernplattformen


  1. Die Seite wird mit folgenden php-Skript erzeugt: SQL_Aufgaben-Funktion

2 Datenbankanbindung mit ESP8266

2.1 Anbindung an MySQL

Starten Sie auf Ihrem PC den MySQL-Datenbankserver, dieser ist dann auf dem Standardport 3306 erreichbar. Die IPv4-Adresse Ihres PCs ermitteln Sie am einfachsten in der Eingabeaufforderung mit ipconfig

Damit sich andere Rechner, also auch der ESP, an der Datenbank anmelden können, muss noch ein Benutzer mit einem Passwort, eine Datenbank und darin eine Tabelle angelegt werden. Gehen Sie dazu wie folgt vor:

  • http://localhost/phpmyadmin/ öffnen
  • Benutzerkonten - Benutzerkonto hinzufügen
  • Tragen Sie einen Benutzernamen und ein Passwort ein, achten Sie darauf, dass bei Hostname 'Jeder Host' eingestellt ist.
  • Haken setzten bei: 'Erstelle eine Datenbank mit gleichem Namen und gewähre alle Rechte.'
  • mit OK abschließen
  • Wählen Sie die neue Datenbank aus und legen Sie darin mindestens eine Tabelle an.
    z.B.: CREATE TABLE IF NOT EXISTS daten ( zeit timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, temp float NOT NULL )

Installieren Sie in der Arduino-IDE über 'Werkzeuge - Bibliotheken verwalten...' den Mysql Connector. Nachdem die beiden Header-Dateien #include <MySQL_Connection.h> und #include <MySQL_Cursor.h> inkludiert wurden, steht die Datenbankfunktionalität zur Verfügung. Ein ausführliche Dokumentation und Erläuterung der Beispiele finden Sie hier.

Zuerst muss im Deklarationsteil mit MySQL_Connection conn((Client *)&wifiClient); eine Datenbankverbindung instanziert werden. Dabei ist &wifiClient der Zeiger auf den zuvor instanzierten WiFi-Client.

Im Initialisierungsteil wird dann mit conn.connect(server_addr, 3306, DBuser, DBpassword); die Verbindung zum Datenbank-Server hergestellt. Hierbei sollte gewartet werden, bis die Verbindung erfolgreich ist.

In der Ausführungsschleife können mit MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn); cur_mem->execute(SQL-query); beliebige SQL-Abfragen an die Datenbank gesendet werden.
Nutzen Sie zum Schreiben Ihrer Messwerte INSERT INTO ....

Öffnen Sie das Beispiel 'Datei - Beispiele - MySQLConnector Arduino - basic_insert_esp8266' in der Arduino-IDE.

Arbeitsauftrag:

  1. Messen Sie mit dem TMP36-Sensor die Raumtemperatur. Diese Temperaturwerte sollen in regelmäßigen Abständen in eine MySQL-Datenbank eingetragen werden. Speichern Sie zu jedem Wert auch den Zeitstempel.
  2. Sie sollen den Verbrauch eines Pelletofens mit Hilfe eines ESPs protokollieren. Jedesmal, wenn ein neuer Sack (15kg) Pellets in den Vorratsbehälter des Ofens gefüllt wird, soll auf einen Taster gedrückt werden.
    Schreiben Sie ein Programm, das nach Druck auf den Taster aus einer Datenbanktabelle den größten Wert ausliest, 15 addiert und einen neuen Datensatz in die Tabelle schreibt. Dabei soll der aktuelle Zeitstempel ebenfalls erfasst werden.
    Nutzen Sie ebenfalls den DeepSleep-Modus.

3 Grafana

Grafana ist ein sehr mächtiges Tool zur Visualisierung von (fast) beliebigen Daten auf Dashboards. Die Daten können u. a. von unterschiedlichen Datenbankmanagementsystemen bezogen werden, z.B. auch von MySQL und InfluxDB.

3.1 Installation

Normalerweise wird Grafana von einem Server in Ihrem Netzwerk oder zu Hause auch von Ihrem Raspberry Pi zur Verfügung gestellt. Hierbei muss das System auch entsprechend abgesichert werden. Im Unterricht ist es am einfachsten, wenn Grafana lokal auf Ihrem PC genutzt werden kann.

  1. Laden Sie das Programm für Ihren Computer herunter: https://grafana.com/grafana/download
  2. Öffnen Sie die Eigenschaften der zip-Datei und setzen Sie den Haken bei 'Zulassen' unter 'Sicherheit'
  3. Entpacken Sie die zip-Datei
  4. Öffnen Sie den Ordner C:\grafana-7.3.7\conf und erstellen Sie eine Kopie der Datei sample.ini, die Sie anschließend in custom.ini umbenennen. Änderungen dürfen nur in dieser Datei vorgenommen werden.

3.2 Grafana starten

Um mit Grafana zu arbeiten, führen Sie die folgenden Schritte aus:

  1. Starten Sie c:\grafana-7.3.7\bin\grafana-server.exe
  2. Öffnen Sie in Ihrem Browser die Seite http://localhost:3000 Benutzer und Passwort lauten 'admin'
  3. Im nächsten Schritt werden Sie aufgefordert ein neues Passort einzugeben.
    (Falls Sie das neue Passwort vergessen sollten, führen Sie über die Kommandozeile im Pfad cd "C:\grafana-7.3.7\bin" den Befehl grafana-cli.exe admin reset-admin-password passwdneu aus.)

3.3 Daten visualisieren

WICHTIG: in der Praxis muss für den Zugriff auf die Datenbank durch Grafana ein Benutzer angelegt werden, der nur SELECT auf einer bestimmten Tabelle ausführen darf.

  1. Um Daten visualisieren zu können, müssen zunächst welche zur Verfügung stehen. Falls Sie keine Temperaturdaten in Ihrer MySQL-Datenbank gespeichert haben, können Sie dieses SQL-Skript importieren.
  2. Wählen Sie 'Add data source', um Grafana mit einer Datenbank zu verbinden.
    Wählen Sie Ihre lokale MySQL-Datenbank, der Benutzer ist 'root' ohne Passwort.
  3. Stellen Sie die Daten in einem Graphen dar. (Beachten Sie, dass die Temperaturdaten in dem Skript im Dezember 2020 erstellt wurden.)
  4. Richten Sie in Grafana eine Ansicht ein, mit der die Daten ohne Eingabe eines Passworts angezeigt werden können.
    Dokumentieren Sie die hierzu notwendigen Schritte.


4 Time-Series-Datenbanken[7]

Am Beispiel von InfluxDB[8]. Diese Datenbank zählt zu den NoSQL-Datenbanken und speichert die Daten im Gegensatz zu einer relationalen Datenbank schemalos. Das bedeutet, dass keine Tabellen angelegt werden sondern sich die Struktur aus den Daten selbst ergibt. Daher eignet sie sich für die Speicherung von Messwerten, da sie mit einer zeitlichen Auflösung im Nanosekundenbereich schneller ist als eine SQL-Datenbank und Daten mit einer SQL-ähnlichen Abfragesprache auch automatisch einfacher zusammengefasst werden können. Wie bei relationalen Datenbanken ist eine genaue Planung der Speicherung für die spätere Auswertbarkeit zwingend erforderlich. Zudem gibt es zahlreiche Konnektoren, z.B. für NodeRed, ESP8266 und Grafana.

Weitere Informationen:

4.1 Installation

Achten Sie bei produktivem Einsatz einer InfluxDB auf eine Absicherung und ein User-Management!

4.1.1 Docker-Container

  1. Starten Sie einen InfluxDB-Container: https://hub.docker.com/_/influxdb in der Version 1.8.6. Erstellen Sie dabei für die Datenbank ein Volume.
  2. Öffnen Sie die Kommandozeile in diesem Container.

4.1.2 Lokale Installation

InfluxDB ist für alle gängigen Server-Betriebssystem erhältlich - die aktuelle Version leider nicht mehr für Windows.

  1. Installieren Sie InfluxDB, indem Sie diese zip-Datei entpacken[9]. Weitere Versionen und andere Programme finden Sie hier.
  2. Starten Sie die Datenbank durch Ausführen des Dienstes: C:\influx-1.8.4-n>influxd.exe. Das Fenster darf nicht geschlossen werden. Der Dienst kann mit Strg+C beendet werden.
  3. Öffnen Sie eine weitere Eingabeaufforderung und starten Sie mit C:\influx-1.8.4-n>influx.exe -precision rfc3339 das CLI (Command Line Interface) der Datenbank. Durch den Parameter werden die Timestamps in einem verständlichen Format ausgegeben.
    Verlassen Sie später das CLI mit exit.

4.2 Daten erfassen

Zur Speicherung muss zunächst eine Datenbank angelegt werden create database datenbankname. Danach muss diese Datenbank ausgewählt werden use datenbankname.

Jetzt können beliebige Datenpunkte eingefügt werden. Hierbei muss der Name der Messungen angeben werden (z.B. 'temp'), was in etwa der Tabelle im relationalen Datenmodell entspricht. Ein Datenpunkt besteht hierbei aus:

  • tag value - z.B. 'Bad' (entspricht dem Spaltennamen)
  • field value - die Messwerte, Standard ist der Datentyp float, andere sind möglich, nach der ersten Speicherung muss der Typ beibehalten werden
  • timestamp - optional, wenn er fehlt, wird er automatisch vom Server übernommen

Hier einige Beispiele:
insert temp,ort=Bad,sensor=1 value=22.8
insert temp,ort=Bad,sensor=1 value=23.2 1613415973169237754 - hier wurde ein Timestamp angegeben
insert pres,ort=Bad,sensor=1 value=825

Datenpunkt können nach ihrer Speicherung nicht mehr verändert oder gelöscht werden.

  1. Legen Sie über das CLI eine neue Datenbank an und fügen Sie ca. zwanzig beliebige Datenpunkte gemäß obigem Beispiel mit unterschiedlichen Tag Values, Field Values und Werten ein.
  2. Schreiben Sie mit dem ESP8266 Daten direkt in die InfluxDB
    1. Installieren Sie in der Arduino-IDE über die Bibliotheksverwaltung die Erweiterung 'ESP8266 influxdb' von Tobias Schürg[10]
    2. Öffnen Sie 'Datei - Beispiele - ESP8266 - BasicWrite'
    3. Schreiben Sie in regelmäßigen Zeitabständen Werte in die InfluxDB. Nutzen Sie dazu entweder einen Poti, Zufallszahlen oder inkrementierte Werte.

4.3 Daten auswerten

Zur Auswertung der Daten steht die Abfragesprache InfluxQL zur Verfügung, die stark an SQL angelehnt ist. Mit dem Befehl show measurements können die Messungen aus der Datenbank ausgegeben werden. Genauere Informationen zu den Inhalten erhält man mit den Befehlen show series, show tag keys und show field keys. Die Daten lassen sich dann mit SELECT-Abfragen ausgeben - z.B. select * from temp - und mit where und group by einschränken und gruppieren.

  1. Daten importieren
    1. Laden Sie die Datei https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt herunter und speichern Sie diese im Verzeichnis der Influx-Datenbank. Diese Datenbank enthält 15.258 Datenpunkte zur Wasserqualität an zwei Orten, die zwischen dem 17.08.2019 und 17.09.2019 erhoben wurden.
    2. Importieren Sie die Datei mit dem Befehl influx -import -path=NOAA_data.txt -precision=s
  2. Dokumentieren Sie die Struktur der beiden Datenbanken mit den oben genannten Befehlen.
  3. Erstellen Sie verschiedene Abfragen auf die Daten, die folgendes ausgeben:
    1. alle Daten in der 'temp'-Messung
    2. alle Daten in der 'temp'-Messung, die Werte enthalten
    3. alle Daten des Sensors 1 in der 'temp'-Messung
    4. alle Daten in der 'temp'-Messung aus dem Bad
    5. alle Daten in der 'temp'-Messung, bei denen der Wert im Bad unter 21°C liegt
    6. alle Daten in der 'temp'-Messung gruppiert nach Ort
    7. alle Daten in der 'temp'-Messung, die in den letzten 30 Minuten geschrieben wurden

Links:

4.4 Daten automatisiert weiterverarbeiten

Mit Continous Queries können Daten von mehreren Messung zu einem neuen Messwert zusammengefasst werden und anschließend mit einer Retention Policy automatisiert gelöscht werden.

Links:

Arbeitsauftrag:

  1. Zeigen Sie zunächst die Datenpunkte Ihrer Datenbank an. Halten Sie fest, wie diese zusammengefasst werden sollen. Erstellen Sie anschließend eine Abfrage, die die Datenpunkte sinnvoll zusammenfasst und kontrollieren Sie das Ergebnis.

4.5 Daten visualisieren

Influxdata stellt ein eigenes Visualisierungs-Tool names Chronograf zur Verfügung, allerdings lassen sich ebenso andere andere Tools nutzen.

  1. Visualisieren Sie die erfassten Daten mit Grafana.


5 Hausautomation mit Home Assistant[11]

Arbeitsauftrag:

  1. Installieren Sie Home Assistant (https://www.home-assistant.io/installation/) auf einer beliebigen Plattform.
    Anschließend rufen Sie die Startseite mit http://homeassistant.local:8123 auf
  2. Fügen Sie einen OpenWeatherMap-Sensor hinzu und zeigen Sie die Wetterdaten z.B. von Dillenburg auf dem Dashboard an. Hierzu müssen Sie sich registrieren und einen API-Key erstellen.
  3. Wechseln Sie im Supervisor-Menü in den Add-on-Store und fügen Sie den File-Editor hinzu.
  4. Installieren Sie die Home Assistant-App auf Ihrem Smartphone und geben Sie alle Sensoren frei.
  5. Zeigen Sie auf der Übersicht den Füllstand des Akkus an und geben Sie eine Warnung aus, wenn dieser 80% überschreitet.
  6. Erkennen Sie, ob jemand zu Hause ist und zeigen Sie diesen Status auf der Übersichtsseite an.
    Hierfür gibt zwei Möglichkeiten:
    1. greifen Sie auf den Sensor der Home Assistant-App zu
    2. über Ihren Router, ob Ihr Smartphone im heimischen WLAN eingebucht ist

6 Container-Virtualisierung

Nach Bearbeitung dieses Kapitels können Sie ...

  • ... den Unterschied zwischen Container- und Betriebssystem-Virtualisierung erklären
  • ... Container starten und mit Volumes verbinden
  • ... mehrere Container starten, die untereinander in Abhängigkeit stehen

Docker ist eine Software, mit der Server-Dienste in Containern virtualisiert werden können und getrennt voneinander laufen. Der Container beinhaltet ein Programm mit all seinen Abhängigkeiten, wodurch er sich in allen Umgebungen identisch verhält, was seine Portierung stark vereinfacht. Dabei nutzen die Container gemeinsam das Host-Betriebssystem. Es besteht die Möglichkeit, fertige Images zu nutzen oder diese selbst zusammen zu stellen.

Warum man unbedingt Docker lernen muss:[12]

6.1 Begriffe[1]

Image
ein Speicherabbild eines Containers. Das Image selbst besteht aus mehreren Layern, die schreibgeschützt sind und somit nicht verändert werden können. Ein Image ist portabel, kann in Repositories gespeichert und mit anderen Nutzern geteilt werden. Aus einem Image können immer mehrere Container gestartet werden.
Container
als Container wird die aktive Instanz eines Images bezeichnet. Der Container wird also gerade ausgeführt und ist beschäftigt. Sobald der Container kein Programm ausführt oder mit seinem Auftrag fertig ist, wird der Container automatisch beendet.
Layer
ein Layer ist Teil eines Images und enthält einen Befehl oder eine Datei, die dem Image hinzugefügt wurde. Anhand der Layer kann die ganze Historie des Images nachvollzogen werden.
Dockerfile
eine Textdatei, die mit verschiedenen Befehlen ein Image beschreibt. Diese werden bei der Ausführung abgearbeitet und für jeden Befehl ein einzelner Layer angelegt.
Repository
ein Repository ist ein Satz gleichnamiger Images mit verschiedenen Tags, zumeist Versionen.
Registry
eine Registry, wie zum Beispiel Docker Hub oder Artifactory, dient der Verwaltung von Repositories.
libcontainer
eine Schnittstelle zu den Grundfunktionen von Docker.
libswarm
eine Schnittstelle, um Docker-Container zu steuern.
libchan[2]
ermöglicht eine einfache („light weighted“) Kommunikation zwischen Prozessteilen und Prozessen.

6.2 Docker installieren

Docker steht für die gängigen Plattformen - Linux, Raspberry Pi, Windows, Mac - zur Verfügung[13]. Wenn Docker unter Windows installiert wird, muss auch das Windows-Subsystem Linux (WSL 2) installiert werden[14]. Docker kann nicht in einer Virtuellen Maschine installiert werden.

Unter Linux sollte man den eigenen Benutzer mit sudo usermod -aG docker $USER zur Gruppe 'docker' hinzufügen, damit nicht bei jedem Befehl 'sudo' angegeben werden muss[15]. Dieser Eintrag wird nach erneuter Anmeldung wirksam.

Play with Docker[16] stellt neben zahlreichen Tutorials auch eine Testumgebung bereit.

6.3 Wichtige Befehle[3]

Befehl Funktion
docker version zeigt die installierte Docker-Version an
docker run <Image> startet einen Container und lädt das Image aus dem Docker-Hub[17]
docker ps zeigt alle laufenden Container
docker ps -a zeigt alle Container, auch nicht laufende
docker stop <Container> stoppt einen Container
docker restart <Container> startet einen Container neu
docker inspect <Container> zeigt umfangreiche Informationen über den angegebenen Container
docker image ls zeigt heruntergeladene Images
docker image prune löscht nicht verwendete Images
docker volume create <VolName> erzeugt ein Volume[18]
docker volume prune löscht nicht verwendete Volumes (Vorsicht ist geboten)
docker stop $(docker ps -a -q) hält alle Container an
docker rm $(docker ps -a -q) löscht alle Container

6.4 Image verwenden

Das Docker-Image, wie man es z.B. aus dem Docker-Hub[19] herunterladen kann, ist die Grundlage für den Container. Neben dem eigentlichen Programm enthält es alle Abhängigkeiten, daher verhalten sich Container auf allen Systemen gleich.

Jeder, der ein Konto auf dem Docker-Hub anlegt, kann dort Images ablegen. Da hierbei keine weiteren Kontrollen stattfindet, können diese Images auch Schadsoftware enthalten. Daher sollte man zu Beginn nur offiziellen Images vertrauen und die Dokumentation sorgfältig lesen.

6.4.1 Einzelnen Container starten

Der Docker-Hub[20] stellt zahlreiche fertige images bereit. Da ein Container den Kernel des Betriebssystems benutzt, muss bei der Auswahl eines fertigen Images dieses eingestellt werden.

Das folgende Beispiel lädt das Images für den Webserver nginx herunter, startet ihn als Hintergrunddienst (-d), der auf Port 8080 hört und diesen an den Port 80 im Container weiter leitet. Der Container erhält den Namen mein-nginx:
docker run --name mein-nginx -d -p 8080:80 nginx

Wenn man auf die Shell innerhalb des Containers zugreifen will: (hierfür muss das Image eine Shell bereitstellen)
docker exec -it mein-nginx bash

Der Container kann mit docker stop mein-nginx angehalten und mit docker rm mein-ngingx gelöscht werden.

6.4.2 Daten persistent speichern

Ein Container existiert nur temporär und kann keine Daten dauerhaft speichern. Um das persistente Speichern und Bereitstellen von Daten zu ermöglichen, werden beim Starten des Containers Volumes verbunden[21]. Dort bleiben die Daten auch nach dem Löschen des Containers erhalten.

Man unterscheidet drei Arten von Volumes:

Host Volumes
man legt selbst fest, welches Verzeichnis des Host-Computer mit welchem Verzeichnis in dem Container verbunden werden soll.
docker run -v <Host-directory>:<Container-directory> <Image>
Anonymous Volumes
hier wird nur das Verzeichnis im Container angegeben. Das Verzeichnis auf dem Host-Computer wird von Docker automatisch festgelegt.
docker run - v <Container directory> <Image>
Named Volumes
für das Volume auf dem Host-Computer wird ein Name vergeben und das Verzeichnis im Container angegeben. Der genaue Ort des Volumes wird ebenfalls von Docker festgelegt.
docker run -v <Name>:<Container directory> <Image>

Die Volumes werden dann beim Starten des Containers automatisch angelegt, Named Volumes können aber auch mit dem Befehl docker volume create <Volume-Name> angelegt werden.

Docker speichert die Inhalte der Volumes im Verzeichnis[4]:

  • Linux: /var/lib/docker
  • Windows: C:\ProgramData\DockerDesktop
  • MacOS: ~/Library/Containers/com.docker.docker/Data/vms/0/

Arbeitsauftrag:

  1. Verbinden Sie ein Host-Volume mit einem Container:
    1. Legen Sie ein Verzeichnis lokal auf Ihrem PC an und und speichern Sie darin eine Datei 'index.html', die Sie mit einem beliebigen Inhalt füllen.
    2. Starten Sie anschließend den nginx[22]-Container und verbinden Sie das Verzeichnis als Host-Volume mit dem Container.
      Als Ergebnis muss im Browser die von Ihnen erstellte Seite angezeigt werden.
    3. Dokumentieren Sie die Vorgehensweise und das Ergebnis.

6.4.3 Mehrere Container starten

Wenn mehrere Container gestartet werden sollen, empfiehlt es sich unbedingt, die Einstellungen für diese Container einen Stack in einer Yaml-Datei[23] zu erstellen und diese mit docker-compose[5] auszuführen. Die Parameter, die mit docker run ... angegeben werden, müssen strukturiert in der Datei gesammelt werden[24]. Die Einrückungen in der Datei müssen unbedingt korrekt strukturiert sein. Die Datei kann vorab überprüft werden, z.B. mit https://yamlvalidator.com/

Die Reihenfolge der Parameter ist für die Funktionalität nicht entscheidend. Es erhöht allerdings die Übersichtlichkeit deutlich, wenn man für alle Container in der Datei die selbe Reihenfolge der Parameter wählt.

Zunächst muss ein Ordner erstellt werden, in dem die Datei docker-compose.yml angelegt wird. Diese Datei hat eine festgelegte Struktur, die sehr gut in [25] und [26] beschrieben wird.

In der ersten Zeile steht die Angabe version:. Diese hängt von der Version der installierten Docker-Engine ab[27]. Anschließend werden unter services: alle zu startenden Container mit den erforderlichen Parametern aufgelistet.

Alle Container, die über eine Datei gestartet werden, befinden sich im selben Netzwerk, das mit dem Namen <Ordnername>_default automatisch erstellt wird. Docker stellt in diesem Netzwerk auch einen internen DNS bereit.

Wenn ein Container den Dienst eines anderen dringend benötigt - wie z.B. WordPress die Datenbank - kann dies unter depends_on: eingetragen werden, damit der WordPress-Container erst gestartet wird, wenn der Datenbank-Container läuft.

Unter environment: können die Umgebungsvariablen für die Konfiguration des Containers eingetragen werden[6]. Welche Variablen benötigt werden, erfährt man in der Dokumentation des Images.

Befehl Funktion
docker-compose up -d startet alle in der Compose-Datei festgelegten Container als Dienst.
Falls restart: always gesetzt ist, wird der Container auch noch Neustart des Hosts wieder gestartet.
docker-compose restart startet alle Container neu
docker-compose stop stoppt vorübergehend alle laufenden Container
docker-compose down stoppt alle Container und löscht sie

Wenn nur einzelne Container gestartet oder beendet werden sollen, muss der Name, der unter 'services:' angeben wurde, angehängt werden.

Wenn ein Named-Volume von mehreren Container gemeinsam genutzt werden soll, muss es unter 'volumes:' in der Yaml-Datei aufgelistet werden.

Alle Angaben können auch in einer beliebigen Datei gespeichert werden. Deren Name kann beim Starten mitgegeben werden: docker-compose -f <Datei>.yml up -d

Arbeitsauftrag

  1. Erstellen Sie eine Yaml-Datei, die alle Einträge enthält, um den nginx-Webserver mit dem Volume zu verbinden und zu starten.
    Kommentieren Sie jede Zeile in Datei mit #.
  2. Erstellen Sie eine Yaml-Datei, mit der Sie eine MySQL-Datenbank[28] starten und mit dem phpmyadmin[29], [30] verwalten können.
    1. Dabei sollen alle Daten der Datenbank und die Konfiguration des phpmyadmins lokal in einem Volume abgelegt werden.
    2. Kommentieren Sie auch hier jede Zeile.
    3. Importieren Sie die Nordwind-Datenbank[31]
  3. Starten Sie mit der Yaml-Datei einen Wordpress-Container[32], der ...
    1. ... den vorhandenen MySQL-Container nutzt und hierin eine eigene Datenbank anlegt. Stellen Sie die Verbindung über die entsprechenden Umgebungsvariablen her.
    2. ... einen eigenen Benutzer für den Datenbank-Zugriff nutzt, der ebenfalls in den Umgebungsvariablen eingetragen wird.
    3. ... Dateien für Themes und Uploads in einem eigenen Volume ablegt.
    4. Kommentieren Sie auch hier jede Zeile.
  4. Ergänzen Sie die Yaml-Datei um die notwendigen Einträge, die mediawiki[33] starten.
    1. Hierbei sollen im Wiki hochgeladene Dateien und Bilder in einem Volume auf dem Host abgelegt werden.
    2. Binden Sie als Datenbank-Server den MySQL-Container an. Für das Wiki soll hierin eine eigene Datenbank angelegt und ein Benutzer hierfür festgelegt werden.
    3. Installieren Sie das Wiki vollständig und legen Sie einen Admin-Benutzer hierfür an.
    4. Kommentieren Sie auch hier jede Zeile.


6.5 Verschiedenes

  1. für die Installation auf einem Raspberry Pi empfehle ich:
    1. mit log2ram werden die log-Datei nicht ständig sondern in festgelegten Zyklen auf die SD-Karte geschrieben.
    2. swap-Datei abschalten[34]

6.6 Links


  1. Quelle: https://de.wikipedia.org/wiki/Docker_(Software)#Begriffe
  2. LinuxMagazinBegriffe, Autor: Michael Unke http://www.linux-magazin.de/ausgaben/2014/09/container/ 2014-09-01
  3. Quelle: c't Wissen - Docker 2020[1] - Seite 15
  4. Quelle: https://www.freecodecamp.org/news/where-are-docker-images-stored-docker-container-paths-explained/ - 17.05.2021 - 23:30
  5. Unter Umständen muss docker-compose noch installiert werden.[2]
  6. Es ist ebenso möglich, diese in einer separaten Datei im selben Verzeichnis zu speichern.


7 Interessante Links