Docker #1 - Installation

Docker Blogbanner

Was ist Docker?

Wenn ich Wikipedia zitieren darf: "Docker ist eine Open-Source-Software zur Isolierung von Anwendungen mit Containervirtualisierung." Damit ist alles gesagt oder? :lol:

In meinem ersten Beitrag der FHEM-Serie "FHEM #1 – geeignete Hardware" habe ich damals das Thema Docker schon einmal etwas gestreift.

Nochmal kurz zum abholen für alle die meinen Beitrag damals nicht gelesen haben. Docker ist bei mir zentraler Bestandteil meines Smart-Homes. Grundsätzlich betreibe ich Docker auf einem ESXi-Server in einer virtuellen Maschine (VM) mit Ubuntu 16.04 LTS. Im Bild wird meine Konfiguration ganz rechts dargestellt (VM Docker):



Bild aus dem VMWare Blog


Man kann Docker natürlich auch direkt ohne virtuelle Maschine unter einem Betriebssystem installieren (Native Docker), was die meisten von euch wahrscheinlich auch so machen werden.

Für die spätere Funktionalität spielt es keine Rolle, ob Docker nativ oder in einer VM installiert wird.

Docker nutzt gewisse Eigenschaften des Betriebssystems, in der Regel ein Linux-Derivat, zur Virtualisierung wie z. B. cgroups, namespaces, SELinux, Netfilter usw. um nur einige davon zu nennen.



Bild von Wikipedia


Wer sich für die Docker-Performance in ESXi-VMs interessiert, dem sei dieser Blogbeitrag an Herz gelegt:
Docker Performance on top of VMware vSphere


Zur Performance-Überwachung kann natürlich wieder Grafana verwendet werden:


Wichtige Begriffe

Vor der eigentlichen Installation zur etwas kurzes zu den wichtigsten Begriffen die später immer wieder mal auftauchen werden.

Container

Der Container ist ein virtuelles Betriebssystem in dem eine Docker-Anwendung installiert werden kann.

Image

Das Image stellt einen komplett fertig konfigurierten Container dar, welcher portiert und kopiert werden kann.

Dockerfile

Im Dockerfile werden Befehle und Parameter definiert um ein Image an bestimmte Anforderungen anpassen zu können.

Docker Hub

Der Docker Hub ist ein großer Marktplatz für fertige Images die dort heruntergeladen/hochgeladen werden können -> hub.docker.com

Installation unter Ubuntu

Zuerst wie immer die Paketliste aktualisieren:

Code
  1. sudo apt-get update

Die einfache Variante installiert Docker unter Ubuntu mittels einem Skript. Für das Skript installiert man zunächst curl mit:

Code
  1. sudo apt-get install curl

Danach ist Docker dran:

Code
  1. sudo curl https://get.docker.com | bash

Nach erfolgter Installation kann man noch überprüfen, ob alles ordnungsgemäß läuft:

Code
  1. sudo systemctl status docker

Es sollte dann so oder so ähnlich aussehen:

Code
  1. docker.service - Docker Application Container Engine
  2. Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: e
  3. Active: active (running) since Fr 2018-01-12 20:01:35 CET; 3 weeks 5 days ago
  4. Docs: https://docs.docker.com
  5. Main PID: 1170 (dockerd)
  6. Tasks: 445
  7. Memory: 186.4M
  8. CPU: 6h 34min 744ms
  9. CGroup: /system.slice/docker.service

Wichtige Kommandos

Alle wichtigen Kommandos in Docker beinhalten das zentrale Kommando docker.

Typischerweise sehen die Befehle so aus:

Code
  1. docker [KOMMANDO]

Die einfache Eingabe von docker ohne weiteres Kommando zeigt eine Liste der möglichen Kommandos und Optionen.

Code
  1. docker [KOMMANDO] --help

Dieser Befehl zeigt einem weitere Informationen zu einem bestimmten Kommando.

Mit

Code
  1. sudo docker info

kann der Status eines Docker-Systems angezeigt werden:


Mit

Code
  1. sudo docker run [IMAGE]

werden Images gestartet. Ist ein Image noch nicht installiert wird es aus dem Docker Hub zuerst heruntergeladen und installiert.

Für einen einfachen Test steht ein Test-Image zur Verfügung, dass wie folgt gestartet werden kann.

Code
  1. sudo docker run hello-world

Das Ergebnis sollte ungefähr so aussehen:

Code
  1. Unable to find image 'hello-world:latest' locally
  2. latest: Pulling from library/hello-world
  3. ca4f61b1923c: Pull complete
  4. Digest: sha256:66ef312bbac49c39a89aa9bcc3cb4f3c9e7de3788c944158df3ee0176d32b751
  5. Status: Downloaded newer image for hello-world:latest
  6. Hello from Docker!
  7. This message shows that your installation appears to be working correctly.
  8. .
  9. .
  10. .


Mit

Code
  1. sudo docker search [Suchbegriff]

kann im Docker Hub nach Images gesucht werden.

Mit

Code
  1. sudo docker ps

werden alle laufenden Container sowie deren Status angezeigt:

Code
  1. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  2. 601150ae19b4 sbiermann/x86-alexa-fhem:latest "start.sh" 8 weeks ago Up 3 weeks 0.0.0.0:3001->3000/tcp alexa

Wichtige Parameter

Data Volumes

Um an Daten zu kommen, die in einen Docker-Container enthalten sind, empfiehlt es sich diese mit dem Hostsystem zu verbinden. Die geschieht über den Parameter -v (volumes).

Mit diesem Parameter kann beispielsweise ein Ordner oder eine Datei im Container liegen und gleichzeitig im Host-System eingebunden (gemountet) sein.

Beispiel an einem Konfigurationsordner eines FHEM-Dockercontainer:

Code
  1. -v /opt/10_docker_fhem_snmp:/opt/fhem \

Links der Bereich vor dem Doppelpunkt zeigt den Pfad auf dem Hostsystem an. Rechts vom Doppelpunkt steht der Pfads innerhalb des Containers.

Das heißt die ganze FHEM-Konfiguration im Container unter /opt/fhem ist gleichzeitig im Hostsystem unter /opt/10_docker_fhem_snmp zu sehen.

Diese Vorgehensweise hat den großen Vorteil, das so zentral vom Hostsystem aus die Konfiguration z.B. angepasst oder gebackupped werden kann. Besonders bei Verwendung von vielen Containern ist das praktisch.




Meine Docker sind möglichst immer so konfiguriert, das die Programmdaten ohne zusätzliches mounting im Container liegen und die Nutzerdaten wie z.B. Konfigurationen usw. im Hostsystem gemountet sind.

Diese Trennung hat den weiteren Vorteil, das Container ganz schnell geupdetet werden können ohne die eigenen Daten zu beeinflussen.

Ports

Ähnlich wie für die volumes verhält es sich mit den Ports und dem Parameter -p

Beispiel wie oben:

Code
  1. -p 8084:8083

Links der Port im Host-System, welcher dem linken im Container entspricht.

Der Vorteil hier. Hat man mehrere gleiche Container parallel am laufen, können diese alle denselben Port innerhalb des Containers verwenden. Nach außen hin zum Host können diese dann zu freien Ports gemappt werden. Sehr vorteilhaft z.B. bei der Verwendung von mehreren FHEM-Dockercontainern gleichzeitig:


Um jetzt z.B. die Weboberfläche eines FHEM-Systems zu erreichen muss ich in meinem Browser nicht die bekannte http://IP-Adresse-FHEM-System:8083 eingeben sondern die

Code
  1. http://IP-Adresse-Docker-Host:8084

Startverhalten

Damit Docker später automatisch nach einem Reboot startet, verwende ich unter Systemen mit systemd folgenden Befehl:

Code
  1. sudo systemctl enable docker

Den Containern gebe ich meistens noch folgenden Parameter mit:

Code
  1. --restart=always

Damit starten auch die Container nach einem Reboot der VM automatisch.

Weitere Optionen lassen sich in der Docker-Dokumention finden.

Portainer

Wer keine Lust hat seine Container über die Konsole zu managen kann hierfür Portainer verwenden.

Portainer stellt eine grafische Oberfläche zur Verwaltung von Containern zur Verfügung.


Installation

Praktischerweise lässt sich Portainer ebenfalls als Dockercontainer installieren. Hierzu muss noch einmal die ebenbesagte Konsole beauftragt werden:

Code
  1. sudo docker run -d \
  2. --restart=on-failure:10 \
  3. --name portainer \
  4. -p 9000:9000 \
  5. -v /var/run/docker.sock:/var/run/docker.sock \
  6. -v /opt/01_docker_portainer/data:/data \
  7. portainer/portainer

Gegebenenfalls sollte man noch den "data"-Pfad an seine eigene Umgebung anpassen oder ohne weiteres Einbinden einfach weglassen.

Die Oberfläche ist dann größtenteils selbsterklärend:




Update eines Containers

Noch kurz meine Vorgehensweise zum Update eines Containers.

Zuerst stoppe und entferne ich den zu updatenden Container:





Meine gemounteten Nutzerdaten von vorher bleiben auf dem Hostsystem bestehen und werden nicht gelöscht.



Danach entferne ich noch das Image:




Jetzt kann man in Portainer den Container wieder hinzufügen:




Da ich das Image vorher gelöscht habe, lädt Docker wieder das aktuellste aus dem Docker Hub herunter und installiert es. Somit ist man wieder auf dem neuesten Stand.

Der Container lässt sich auch in der Konsole wieder starten, was ausnahmsweise ein wenig schneller geht als direkt in Portainer. Danach taucht der Container wie gewohnt in der Containerübersicht auf.

Laufwerke Einbinden per CIFS

Einige meiner Container speichern Daten direkt auf ein freigegebenes Netzlaufwerk in einer anderen VM. Dieses Netzlaufwerk habe ich vorher in mein Hostsystem eingebunden:

Code
  1. sudo nano /etc/fstab

In der fstab habe ich dazu folgendes am Ende eingetragen:

Code
  1. //192.168.178.144/daten0/00_tv-aufnahmen /mnt/server4_VM0/00_tv-aufnahmen cifs username=Benutzer,passwd=Passwort 0 0

Das Beispiel steht für meinen tvheadend-Container, welcher TV-Aufnahmen eines SAT-to-IP-Routers auf dem Netzlaufwerk speichert. IP-Adresse, Pfade, Benutzer, Passwort muss man natürlich anpassen.

Alternativ zur Klartextangabe von Username/Passwort kann auch eine Anmeldedatei verwendet werden. Siehe dazu das Ubuntu-Wiki.

Der dazu passende Docker-Parameter sieht dann wie folgt aus:

Code
  1. -v /mnt/server4_VM0/00_tv-aufnahmen:/recordings

Im Pfad /recordings werden die Aufnahmen im tvheadend-Container gespeichert.

Am Schluss noch die fstab neu einlesen mit

Code
  1. sudo mount -a

Backups

Um von allen wichtigen Nutzerdaten Backups zu erstellen habe ich mir ein kleines bash-script erstellt:

Code
  1. sudo nano docker_backups.sh

Beispielhaft sind die ersten drei Container enthalten. Im Prinzip nur copy & paste.

Ich habe noch einen Spezialfall. Für die MariaDB Datenbank habe ich noch ein extra Backup-script:

Code
  1. sudo nano docker_mariadb_fhem_SQL_backup.sh
Shell-Script
  1. #!/bin/sh
  2. DIR="/home/admin2/docker_mariadb_fhem_SQL_backup"
  3. DATUM=`date '+%Y-%m-%d_%H%M'`
  4. docker exec mariadb-fhem /usr/bin/mysqldump -uuser -ppasswort --all-databases > $DIR/backup.sql
  5. gzip -9 --best $DIR/backup.sql
  6. mv $DIR/backup.sql.gz $DIR/${DATUM}_MariaDb_fhem_DbLog_SQL_dump.sql.gz

Dieses Script erzeugt direkt aus Docker heraus das Backup und legt es auf dem Hostsystem ab.

Beide Scripte liegen im home Verzeichnis meines admin users.
Danach noch in der crontab definiert, wie oft die Backups erstellt werden sollen:

Code
  1. sudo crontab -e
Code
  1. 0 23 * * 0 /bin/bash /home/admin2/docker_backups.sh
  2. 0 3 * * * /bin/bash /home/admin2/docker_mariadb_fhem_SQL_backup.sh

0 23 * * 0 heißt jeden Sonntag um 23 Uhr

0 3 * * * heißt jeden Tag um 3 Uhr

Dann noch in der crontab eingetragen, das die Backups direkt in meinen Onlinespeicher mittels rsync verschoben werden sollen. Siehe auch meinen FHEM-Backup Artikel dazu.

Code
  1. 0 4 * * * rsync -avrze "ssh" --remove-source-files /home/admin2/docker_backups/ space-XXXX@rsync.hidrive.strato.com:/users/space-XXXX/99_backups_server/backup_server4_VM2_docker/2018/
  2. 0 4 * * * rsync -avrze "ssh" --remove-source-files /home/admin2/docker_mariadb_fhem_SQL_backup/ space-XXXX@rsync.hidrive.strato.com:/users/space-XXXX/99_backups_server/backup_server4_VM2_docker_mariadb_fhem_SQL/2018/

Das Ergebnis in HiDrive-Onlinespeicher sieht dann so aus:




    Über den Autor

    Autor von worldoftech.de. Smart-Home-Verrückter.


    Nutzt Zuhause FHEM zusammen mit HomeMatic, JeeLink, 1-Wire, Flammtronik / Atmos HV, Buderus KM271, Philips HUE, Xiaomi Yeelight, Alexa, Sonos, FritzBox, Ubiquiti UniFi APs, APC UPS, APC PDU, IPMI. MariaDB, InfluxDB und Grafana zur Auswertung. Als Hardware-Untersatz kommen mehrere RaspberryPis und Supermicro Serverhardware zum Einsatz. Softwareseitig werden hauptsächlich Raspbian, Ubuntu, ESXi und Docker verwendet.

    Reinhard Team