Einführung in Docker unter OpenMediaVault 7
geschrieben von Stefan, zuletzt aktualisiert amIn diesem Artikel geben wir euch eine Einführung in das Containermanagement Docker und zeigen euch anhand von OpenMediaVault 7 Schritt für Schritt wie ihr erste Docker Container erstellt und benutzt. Wir nutzen in dieser Anleitung Docker Compose, welches eine einfache aber sehr leistungsstarke Verwaltung von einem oder mehreren Docker Containern ermöglicht.
Unterschiede zur klassischen Virtualisierung
In einem Docker Container lässt sich beliebige Software ausführen und zwar isoliert vom Hostsystem. Die Container können leicht auf andere Systeme kopiert und gestartet werden, eine Neukonfiguration entfällt. Im Grundprinzip ähnelt ein Docker Container einer virtuellen Maschine, denn er enthält eine lauffähige Umgebung, die erstmal isoliert vom Hostsystem arbeitet. Es gibt aber ein paar große Unterschiede zu einer virtuellen Maschine:
1. Ein Docker Container enthält kein Betriebssystem
Im Gegensatz zu einer virtuellen Maschine enthält ein Docker Container kein eigenes Betriebssystem, sondern nutzt den Linux-Kernel des Hostsystems mit Zugriff auf die Linux-Namespaces, die Datenträger sowie den Netzwerk-Stack. Zusätzlich nutzt Docker die Linux-Kontrollgruppen cgroups und die Linux Security Modules (LSM) zur Absicherung der Docker-Prozesse.
Diese Tatsache macht die Installation und Konfiguration eines Docker Containers sehr viel einfacher, da im Docker Container kein Betriebssystem installiert werden muss. Das Image des Docker Containers enthält nur ausgewählte Software sowie deren Abhängigkeiten. Das vereinfacht die Installation und Konfiguration enorm. Auch die CPU-Architektur (z.B. x86-64 oder ARM64) spielt im Gegensatz zu einer virtuellen Maschine eine viel geringere Rolle.
Da die Images kein Betriebssystem enthalten, besitzen diese auch eine viel geringere Dateigröße. Images lassen sich über den Docker Hub oder auch manuell einbinden.
2. Die Hardware des Hostsystems wird direkt genutzt
In einer virtuellen Maschine muss die Hardware emuliert bzw. simuliert werden, dabei werden dann auch feste Limitierungen (z.B. eine bestimmte Anzahl an CPU-Kernen oder eine bestimmte Menge an Arbeitsspeicher oder Speicherplatz zugewiesen). Docker verwendet direkt die Hardware-Ressourcen des Hostsystems was viele Probleme mit virtuallisierter Hardware umgeht.
Auf Wunsch lässt sich für bestimmte Komponenten ein Limit sowie ein Reservierung direkt in der Compose-Einstellungsdatei (dazu später mehr) festlegen. Die Hardwarenutzung ist in der Regel deutlich effizienter als bei einer virtuellen Maschine.
3. Das Image eines Docker Containers ist nicht exklusiv
Erstellt man eine virtuelle Maschine, wird ein VM-Image erstellt, welches eine exklusive Laufzeitumgebung enthält. Betriebssystem, Software und Einstellungen werden in diesem Image gespeichert. Daher kann das Image nur für eine virtuelle Maschine gleichzeitig genutzt werden.
Docker teilt Image und Daten auf, so dass ein Docker Image gleichzeitig von beliebig vielen Docker Containern genutzt werden kann. Jeder Container nutzt dabei seine eigenen Einstellungen und Daten. Setzt man zum Beispiel drei Docker Container mit dem Apache Webserver ein, benötigt man nur einmal das Docker Image welches diese Software enthält. Die drei Container nutzen alle das gleiche Image, können aber komplett anders konfiguriert werden.
Dieser Vorteil wird nicht nur bei der Installation und Konfiguration sichtbar, sondern auch bei Updates: wird eine neue Version des Apache Webservers veröffentlicht, muss nur ein Image aktualisiert werden. Alle drei in diesem Beispiel eingesetzten Docker-Container würden im Anschluss bei entsprechender Konfiguration das aktuelle Docker Image nutzen.
Auf Wunsch können auch mehrere Versionen eines Images beibehalten und entsprechend genutzt werden. Eine neue Version kann so nur auf spezifische Container ausgerollt werden. In der Regel nutzt man allerdings für seine Container die jeweils aktuellste verfügbare Version (wird als :latest in der Compose-Datei gekennzeichnet).
4. Netzwerk-Isolation sofern gewünscht
Standardmäßig ist ein neu erstellter Docker-Container erstmal komplett isoliert und kann weder mit dem Hostnetzwerk kommunizieren noch ist dieser selbst erreichbar. Über die verschiedenen Netzwerkmodi von Docker können nun einzelne Ports des Docker Containers geöffnet werden (bridge Modus) um mit dem Host-Netzwerk bzw. auch den anderen Docker Containern Daten austauschen zu können.
Wahlweise steht auch ein Host-Netzwerkmodus zur Verfügung, bei dem der Docker Container auf allen Ports Daten empfangen kann, die an das Hostsystem gesendet werden. Das kann z.B. bei sehr umfangreicher Software wie etwa der Smarthome Steuerungssoftware Home Assistant Sinn machen, da man im bridge Modus sonst manuell sehr viele Ports öffnen müsste.
5. Hohe Skalierbarkeit
Container können sich dabei über den Docker Swarm Modus auch auf mehreren Hostsystemen befinden. Das ist in der Regel aber vor allem in Firmen interessant und nicht im Heimbereich. Durchgesetzt hat sich hier die Verwaltung über Kubernetes. Kubernetes ist ein von Google entwickeltes Open-Source-System zur Verwaltung von Container-Anwendungen. Es kann zudem Container überwachen und bei Problemen neu starten um eine sehr hohe Verfügbarkeit zu gewährleisten.
Für ein Heimsystem oder NAS ist dieses Feature uninteressant, ich wollte es hier aber einmal kurz erwähnen um zu demonstrieren wie gut Docker skaliert.
Funktionsweise von Docker
Wie schon beschrieben nutzt Docker viele Module des Linux Kernels des Hostsystems. Docker selbst wird dabei als root, also mit vollem Zugriff ausgeführt um auf die Kernel-Module zugreifen zu können. Seit einigen Jahren gibt es aber bei vielen Containern die Möglichkeit eine User-ID und eine Gruppen-ID eines Benutzers des Hostsystems zu übergeben, die dann auch im Container selbst genutzt wird. So lässt sich steuern mit welchen Rechten die Software im Container selbst ausgeführt wird und auf welche Ressourcen diese zugreifen darf.
Auf dem Hostsystem bietet sich ein eigener Benutzer für Docker an, welcher nur begrenzte Rechte besitzt und dessen Dateirechte auf das Docker-Verzeichnis limitiert sind. Generell sind die Container vom Hostsystem über eine Firewall isoliert. Per Befehl werden dann meist nur die benötigten Ports gegenüber dem Host gezielt geöffnet.
Um einen ersten Container in Docker anzulegen, benötigt es nur wenige Zeilen Code. Container lassen sich zwar auch per Befehlszeile direkt anlegen und starten, wesentlich übersichtlicher ist es allerdings eine so genannte Compose Datei zu erstellen. Diese beinhaltet alle externen Einstellungen für einen oder auf Wunsch auch mehrere Container.
Gerade für Anfänger und für kleinere Heimsysteme empfiehlt es sich jeweils eine Compose-Datei pro Container zu erstellen. Das ist übersichtlicher und bei Problemen ist nur ein einzelner Container betroffen.
In größeren Umgebungen werden meist mehrere Container in nur einer Compose-Datei verwaltet, z.B. könnte man in einer einzigen Compose-Datei einen kompletten Stack aus Webanwendungen kombinieren (z.B. den Apache Webserver, PHP, eine MySQL-Datenbank, phpMyAdmin usw.).
Einrichtung in OpenMediaVault 7
Damit die Länge dieser Anleitung nicht komplett gesprengt wird, gehe ich davon aus, das euer System folgende Voraussetzungen erfüllt:
Voraussetzungen:
- Ein System / NAS mit OpenMediaVault 7
- OMV-Extras sind in OpenMediaVault 7 installiert
- Docker repo in den OMV-Extras aktiviert
- Die Erweiterung openmediavault-compose ist installiert
Ist euer System soweit vorbereitet, erstellen wir uns zunächst einen Benutzer, der der Eigentümer der Verzeichnisse und Dateien für unsere Docker Umgebung wird. In meinem Beispiel habe ich mir einen Benutzer mit dem Namen stefan angelegt. Ihr könnt diesen aber auch z.B. docker nennen. Dieser ist Mitglied der folgenden Gruppen:
- users - Standardgruppe für alle Benutzer
- docker - Zugriff auf die Docker Befehlszeile ohne root Rechte
- _ssh - Zugriff auf das System/NAS via SSH (optional)
- sambashare - Freigabe von Verzeichnissen via SMB ohne root-Rechte (optional)
Verzeichnisse und Freigaben
Nachdem wir nun einen Benutzer erstellt haben, müssen wir noch Ordner erstellen, in denen die Docker Compose-Dateien und auch die Daten der Container gespeichert werden. Außerdem gehe ich hier später noch auf das automatische Backup von Containern ein, daher legen wir noch einen dritten Ordner an, in denen das Backup gespeichert werden soll.
Mein NAS speichert alle Daten auf einem RAID 1 Verbund. Das NAS hatte ich euch in meinem Artikel Raspberry Pi 5 NAS bereits vorgestellt.
Auf diesem Raid-Verbund erstelle ich mir nun einen Ordner mit dem Namen "Docker". In diesem Ordner werden alle Docker-Daten von den Containern abgelegt. Es folgen zwei weitere Unterordner "_Compose" sowie "_Backup". Die Namen der Ordner können beliebig sein und dienen als Speicherort für die Compose-Dateien, die die Einstellungen der Container enthalten. Im "_Backup" Ordner wird später das Backup der Container gesichert.
Neu angelegte Verzeichnisse gehören automatisch erstmal dem Benutzer root. Über die Zugriffsrechte bzw. die ACL (Access Control Lists) lässt sich der Besitzer der Verzeichnisse ändern. Wir geben unserem neu angelegten Benutzer stefan hierüber volle Lese- und Schreibrechte auf diese Verzeichnisse und machen diesen über die ACL zum Eigentümer der Verzeichnisse.
Docker Compose konfigurieren
Damit ist die Vorbereitung abgeschlossen und wir können Docker in OpenMediaVault über Dienste - Compose - Einstellungen konfigurieren. Wir werden hier nach dem Verzeichnis für die Compose-Dateien, den Container-Daten sowie dem Backup Verzeichnis gefragt. Außerdem müssen wir hier wieder den Eigentümer der Verzeichnisse auf unseren erstellten Benutzer setzen.
Da Docker mit root-Rechten läuft, muss hier als Eigentümer wieder unser erstellter Benutzer festgelegt werden, da ansonsten die Dateien dem Benutzer root gehören würden. Das kann später zu Problemen führen, wenn wir mit einem anderen Benutzer auf diese Dateien zugreifen wollen.
Den ersten Container erstellen
Nun können wir über den Menüpunkt Dienste - Compose - Dateien unsere erste Compose-Datei erstellen und damit den ersten Container der unter Docker laufen soll. Wir haben hier mehrere Möglichkeiten eine Compose-Datei zu erstellen oder bereits vorbereitete Compose-Dateien herunterzuladen. Wir fangen aber ganz von vorne an und erstellen uns eine zunächst leere Compose-Datei, indem wir Hinzufügen auswählen.
Hier vergeben wir nun einen Namen, auf Wunsch eine Beschreibung und im Feld "Datei" können wir nun die Konfiguration des Containers vornehmen. Den Namen des Containers könnt ihr frei wählen. Bei image geben wir an, welches Image dieser Container aus dem Docker-Hub herunterladen soll. Ich habe hier für unser Beispiel Node-RED gewählt, da der Container einfach zu konfigurieren ist und später über eine Weboberfläche aufgerufen werden kann.
Unter volumes geben wir den Dateipfad auf unserem Hostsystem an, unter welchem der Container seine Daten speichern soll. Hinter dem Hostsystem Datenpfad folgt ein Doppelpunkt und der in dem Container genutzte Speicherpfad.
Da wir in den Docker-Einstellungen bei Daten unseren Pfad angegeben haben (in meinem Beispiel "/srv/dev-disk-by-uuid-06851747-3465-44ab-ad6c-ee9247a3b8e0/Docker"), können wir hier die Variable CHANGE_TO_COMPOSE_DATA_PATH benutzen, die beim Container-Start in den in den Docker-Einstellungen festgelegten Datenpfad aufgelöst wird.
Man kann den Pfad aber auch ohne Variable direkt angeben. Wichtig: bei euch wird die uuid des Pfads sicherlich anders sein als bei mir. Das ist normal. Als letztes geben wir nun noch den Port an, auf dem Node-RED erreichbar sein soll. Gleiche Logik wie beim Speicherpfad (Host : Container). Mit 1880:1880 reicht man den Port direkt auf den Host durch, man könnte den Hostport aber auch abändern, z.B.. in 1882:1880 sofern dieser Port auf dem Hostsystem bereits in Benutzung ist.
Code zum kopieren:
# Node-RED services: nodered: container_name: nodered image: nodered/node-red:latest restart: unless-stopped volumes: - CHANGE_TO_COMPOSE_DATA_PATH/nodered/data:/data ports: - 1880:1880
Damit ist die Konfiguration des ersten Containers bereits abgeschlossen. In der Dateiübersicht von Docker wählt ihr nun den eben erstellten Container aus und wählt in der oberen Menüleiste überprüfen aus. Damit wird die Compose Datei auf eine korrekte Syntax überprüft. Ist alles in Ordnung, könnt ihr den Container nun mit dem Befehl Up über die Menüleiste starten. Docker wird das benutzte Image automatisch herunterladen, sollte es sich noch nicht auf dem Hostsystem befinden.
In der Dateiansicht sollte nun der Status des Containers mit Up gekennzeichnet sein. Ist dies der Fall, ist Node-RED über die IP-Adresse eures Hostsystems gefolgt von einem Doppelpunkt und dem Port 1880 über den Webbrowser erreichbar.
Docker Umgebungsvariablen für einen Container
Einige Container nutzen Variablen um bestimmte Einstellungen innerhalb des Containers zu setzen. Diese Variablen können in der so genannten Environment file gesetzt werden, die in OpenMediaVault über die Bearbeitung der Compose-Einstellungen erreichbar ist.
Das Textfeld für die Umgebungsvariablen könnt ihr über die Checkbox Show environment file aktivieren. Ich habe hier mal ein Beispiel für einen Container erstellt, der die Software MQTT-Explorer enthält. Dies ist aktuell auch mein einziger Container, bei dem Umgebungsvariablen genutzt werden.
Limits für einen Container festlegen
Ich hatte am Anfang des Artikels bereits darauf hingewiesen, dass auch ein Docker Container in seiner Hardwarenutzung limitiert werden kann. Hier gibt es einmal ein Limit, welches definiert wie viele Ressourcen des Hostsystems ein Container maximal benutzen darf. Zusätzlich ist es über eine Reservierung möglich einem Container eine bestimmte Menge an Ressourcen zu reservieren, die nicht von anderen Containern genutzt werden können.
Ich verwende auf meinem System gar keine Einschränkungen oder Reservierungen für meine Container, möchte euch aber der Vollständigkeit halber die Möglichkeit hier zeigen:
deploy: resources: limits: cpus: '1' memory: 1024M reservations: cpus: '0.5' memory: 512M
In diesem Beispiel darf der Container maximal 1 logischen CPU-Kern sowie 1024 MB an Arbeitsspeicher nutzen. Außerdem werden nur für diesen Container immer 0,5 logische CPU-Kerne sowie 512 MB garantiert (reserviert).
Automatisches Backup und Update der Container
OpenMediaVault 7 bietet die Möglichkeit eure Container (also die Compose-Einstellungen sowie die Daten der Container) automatisiert zu sichern. Nach dem Backup lässt sich auch eine Aktualisierung der benutzen Image-Dateien durchführen. Wählt ihr hier bei Filter * aus, werden alle Container gesichert und aktualisiert, ihr könnt aber auch nur gezielte Container auswählen.
Als letzte Option kann der Docker Befehl Prune ausgeführt werden, der eure Docker-Umgebung von nicht benutzen Ressourcen wie alten Image-Dateien oder nicht benutzten Containern und Netzwerkkonfigurationen bereinigt.
Bei mir wird das Backup bzw. die Aktualisierung wöchentlich ausgeführt. Dabei kann immer nur eine Version des Backups im Backup-Verzeichnis existieren. Alte Backups werden also automatisch überschrieben. Möchtet ihr mehrere Backup-Versionen beibehalten, könnt ihr zum Beispiel ein Script vor dem Backup ausführen, welches die alten Dateien in einen anderen Ordner verschiebt.
Wer mehr über Docker erfahren möchte, dem empfehle ich meine Anleitung Einführung in Docker unter OpenMediaVault 7. Hier geht es nicht nur um OpenMediaVault, sondern vor allem um Docker und wie das Containermanagement aufgebaut ist.
Bei Links, die mit einem * gekennzeichnet sind, handelt es sich um Affiliate-Links, bei denen wir bei einem Kauf eine Vergütung durch den Anbieter erhalten.
Kommentare (0)
Diesen Artikel kommentieren:
Hinweis:
- Nur Fragen / Antworten direkt zum Artikel
- Kein Support für andere Hard- oder Software !
Spamfreies E-Mail Abo nur bei neuen Artikeln