Docker #1 - Installation

Docker #1 – Installation

Docker #1 - Installation

Heute ein Tutorial zu Docker und wie man es einfach installieren kann. Dieser Artikel ist auch eine wichtige Grundlage für weitere super interessante Artikel rund um das Thema Smart-Home.

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?  😆

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):

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.

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:

sudo apt-get update

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

sudo apt-get install curl

Danach ist Docker dran:

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

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

sudo systemctl status docker

Es sollte dann so oder so ähnlich aussehen:

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

Wichtige Kommandos

Alle wichtigen Kommandos in Docker beinhalten das zentrale Kommando docker.

Typischerweise sehen die Befehle so aus:

docker [KOMMANDO]

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

docker [KOMMANDO] --help

Dieser Befehl zeigt einem weitere Informationen zu einem bestimmten Kommando.

 

Mit

sudo docker info

kann der Status eines Docker-Systems angezeigt werden:

Containers: 16
 Running: 14
 Paused: 0
 Stopped: 2
Images: 13
Server Version: 17.05.0-ce
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 141
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
.
.
.

 

Mit

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.

sudo docker run hello-world

Das Ergebnis sollte ungefähr so aussehen:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:66ef312bbac49c39a89aa9bcc3cb4f3c9e7de3788c944158df3ee0176d32b751
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
.
.
.

 

Mit

sudo docker search [Suchbegriff]

kann im Docker Hub nach Images gesucht werden.

 

Mit

sudo docker ps

werden alle laufenden Container sowie deren Status angezeigt:

CONTAINER ID  IMAGE                            COMMAND      CREATED       STATUS      PORTS                  NAMES                                                  
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:

-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.

Docker #1 - Installation unter Ubuntu und Raspbian

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:

-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:

Docker #1 - Installation unter Ubuntu und Raspbian

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

http://IP-Adresse-Docker-Host:8084

Startverhalten

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

sudo systemctl enable docker

Den Containern gebe ich meistens noch folgenden Parameter mit:

--restart=always

Damit starten auch die Container nach einem Reboot 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.

Docker #1 - Installation unter Ubuntu und Raspbian

Installation

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

sudo docker run -d \
--restart=on-failure:10 \
--name portainer \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/01_docker_portainer/data:/data \
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:

Docker #1 - Installation Docker #1 - Installation

Update eines Containers

Noch kurz meine Vorgehensweise zum Update eines Containers.

Zuerst stoppe und entferne ich den zu updatenden Container:

Docker #1 - Installation unter Ubuntu und Raspbian

Docker #1 - Installation unter Ubuntu und Raspbian

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

Docker #1 - Installation unter Ubuntu und Raspbian

Danach entferne ich noch das Image:

Docker #1 - Installation unter Ubuntu und Raspbian Docker #1 - Installation unter Ubuntu und Raspbian

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

Docker #1 - Installation unter Ubuntu und Raspbian

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:

sudo nano /etc/fstab

In der fstab habe ich dazu folgendes am Ende eingetragen:

//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:

-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

sudo mount -a

Backups

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

sudo nano docker_backups.sh
#!/bin/sh
DIR1="/home/admin2/docker_backups"
DATUM=`date '+%Y-%m-%d_%H%M'`

tar -vczf $DIR1/archiv.tar.gz /opt/01_docker_portainer/
mv $DIR1/archiv.tar.gz $DIR1/${DATUM}__01_docker_portainer.tar.gz

tar -vczf $DIR1/archiv.tar.gz /opt/02_docker_sabnzbd/
mv $DIR1/archiv.tar.gz $DIR1/${DATUM}__02_docker_sabnzbd.tar.gz

tar -vczf $DIR1/archiv.tar.gz /opt/03_docker_syncthing/
mv $DIR1/archiv.tar.gz $DIR1/${DATUM}__03_docker_syncthing.tar.gz
.
.
.

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:

sudo nano docker_mariadb_fhem_SQL_backup.sh
#!/bin/sh
DIR="/home/admin2/docker_mariadb_fhem_SQL_backup"
DATUM=`date '+%Y-%m-%d_%H%M'`
docker exec mariadb-fhem /usr/bin/mysqldump -uuser -ppasswort --all-databases > $DIR/backup.sql
gzip -9 --best $DIR/backup.sql
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:

sudo crontab -e
0 23 * * 0 /bin/bash /home/admin2/docker_backups.sh
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.

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/

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:

Docker #1 - Installation unter Ubuntu und Raspbian

Docker #1 - Installation unter Ubuntu und Raspbian

Reinhard

Autor von frombeyond.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.