Container mit Docker in der Praxis

Container waren bis vor kurzer Zeit ein grosser Hype. Aktuell liest man nicht mehr so viel darüber, findet jedoch bei immer mehr Software statt eines Installers oder Pakets nur ein Dockerfile. Das zeigt, dass Container in der Praxis angekommen sind. Trotzdem haben immer noch viele Administratoren wenig Ahnung davon.

Dieser Artikel erklärt die Installation eines Hosts inkl. Einrichtung einiger Container darauf. Es soll ein Szenario gezeigt werden, welches für kleine und mittlere Unternehmen relevant ist.

Grundlagen

Für die Grundlagen sei auf folgende Seiten verwiesen:

Docker auf Windows

Docker kommt aus der Unix-Welt. Es läuft auch unter Windows, aber hier sind einige Sachen zu beachten.

Docker auf Windows 10

Auf Windows 10 lassen sich mit Docker nur Linux-Container betreiben. Diese laufen in einer automatisch installierten Linux-VM ("MobyLinux"). Für die Virtualisierung wird Hyper-V verwendet, man benötigt also Windows 10 Pro, Enterprise oder Education sowie kompatible Hardware.

Sind die Anforderungen erfüllt, lässt sich Docker wie eine normale Anwendung installieren. Der Download von https://download.docker.com/win/stable/Docker%20for%20Windows%20Installer.exe erspart einem die Erstellung eines Benutzerkontos auf docker.com.

Docker auf Windows Server

Seit Version 2016 bietet Windows die Unterstützung von Containern an. Diese besteht aus zwei Teilen: dem Windows-Feature "Container", welches Windows-Container bereitstellt sowie Docker Enterprise, welches für deren Verwaltung sorgt.

Für den Betrieb von Containern gibt es zwei Varianten:

  • Prozess-Isolation: Alle Container laufen auf dem Host-Kernel. Das ist vergleichbar mit Containern unter Linux.
  • Hyper-V-Isolation: Jeder Container läuft in einer eigenen virtuellen Maschine. Die Virtualisierung erfolgt über Hyper-V.

Auf https://docs.docker.com/ee/docker-ee/windows/docker-ee/ ist die Installation von Docker unter Windows Server ausführlich beschrieben.

Für unseren Zweck kommt Windows leider nicht in Frage. Aus einem einfachen Grund: ich habe in der Praxis noch keine Windows Container gesehen. Linux-Container benötigen das Feature "Linux containers on Windows" (LCOW) und dieses ist erst als Preview verfügbar.

Wir installieren deshalb eine Linux-VM auf Hyper-V und lassen die Container darin laufen. Das ist näher an der Praxis für die meisten Firmen.

Docker auf Linux

Unter Linux lässt sich Docker wie andere Software installieren. Es ist in jeder populären Distribution als Paket vorhanden. Wer schon mit Linux arbeitet, kann also gut die Distribution verwenden, die er kennt.

Ich arbeite im Serverbereich meist mit Debian. Hier versuche ich es mal mit Alpine Linux. Dieses wurde mir als Host für Container empfohlen, da es eine sehr schlanke Distribution ist. In der Tat: ein Installations-ISO von nur 40 MB findet man heutzutage selten!

Das ISO kann man auf https://www.alpinelinux.org/downloads/ beziehen. Ich habe die Variante "Virtual" gewählt.

Die Installation in der VM ist selbsterklärend. Für Hyper-V ist zu beachten, dass die Integration Tools noch nachinstalliert werden sollten. Dies ist auf https://wiki.alpinelinux.org/wiki/Hyper-V_guest_services beschrieben.

Für Docker muss eine zusätzliche Paketquelle installiert werden. Wer den Texteditor "vi" nicht mag, kann mit "apk add nano" den einsteigerfreundlicheren Editor "nano" installieren.

Danach editiert man mit "nano /etc/apk/repositories" die Liste der Paketquellen. Man muss den Kommentar ("#") bei der Community-Quelle entfernen.

Nun die Quellen mit "apk update" aktualisieren und Docker mit "apk add docker" installieren. "rc-update add docker boot" startet Docker automatisch beim Systemstart und "service docker start" startet den Dienst sofort. Wenn "docker ps" keine Fehlermeldung ausgibt, sind wir bereit.

erste Schritte

Zum Test starten wir einen Container, welcher ein Ubuntu enthält. Wir verbinden unser Terminal damit ("-it") und starten die Bash-Shell:

docker run -it ubuntu bash

Weil das Image lokal noch nicht vorhanden war, wurde es automatisch heruntergeladen. Jetzt befinden wir uns im Container:

Mit "Ctrl+P", gefolgt von "Ctrl+Q" können wir den Container verlassen, ohne ihn zu beenden.

"docker ps" zeigt ihn jetzt an:

Mit "docker attach 7b23f0fa8463" können wir uns wieder in den Container verbinden. Um nicht die ID verwenden zu müssen, hätten wir dem Container gleich beim Start mittels "--name" einen Namen geben oder ihn danach mit "docker rename" umbenennen können.

Wenn wir den Container mittels "exit" verlassen oder mit "docker stop" beenden, wird er von "docker ps" nicht mehr aufgelistet, wohl aber von "docker ps -a".

Wollen wir ihn wieder starten, verwenden wir "docker start -ai". Ein erneuter Aufruf von "docker run" würde einen neuen Container ausgehend vom selben Image starten. Wollen wir zehn Container mit einem Webserver starten, führen wir zehnmal "docker start" mit einem Webserver-Image aus. Es läuft dann nicht ein Container zehnfach, sondern es laufen zehn Container, welche vom gleichen Image aus gestartet wurden.

Datenpersistenz

Ein Vorteil von Containern ist, dass man die Software darin nicht updaten muss, sondern dass man bei Updates das darunterliegende Image austauscht. Betreibt man MariaDB in einem Container und es erscheint eine neue Version, aktualisiert man das Image und startet einen neuen Container von diesem Image.

Das bedingt natürlich, dass in den Containern keine Benutzerdaten und Konfigurationen gespeichert sein dürfen. Man will ja nicht bei jedem Update von WordPress seine Website neu erstellen...

Um Daten persistent zu speichern, kann man lokale Verzeichnisse in Container mounten. Die Konfiguration von Containern erfolgt häufig über Umgebungsvariablen, die vor dem Start gesetzt werden.

Als Test starten wir einen Container, veranlassen, dass er beim Beenden entfernt wird ("--rm") und mounten das lokale Verzeichnis "/test" als "/test" in den Container. Im Container erstellen wir eine Textdatei in diesem Verzeichnis. Nach dem Beenden inkl. automatischer Lösung des Containers (nicht des Images) sehen wir auf dem Host die im Container erstellte Datei:

docker-compose

Mit dem Tool docker-compose lassen sich mehrere Container gleichzeitig erstellen und konfigurieren. Da man Container nicht aktualisiert, sondern durch von aktualisierten Images erstellte Container ersetzt, ist es sinnvoll, pro Dienst einen Container zu haben. So kann man beispielsweise den Datenbankserver separat updaten.

Konfigurationsdateien für docker-compose heissen "docker-compose.yml" und werden in einem eigenen Verzeichnis abgelegt. Man startet docker-compose dann von diesem Verzeichnis aus.

Praxistipp: Um einen Befehl in einem Container auszuführen, kann man "docker-compose exec" verwenden. Um in die Datenbanken auf dem im nächsten Schritt erstellten Nextcloud-Datenbankserver zu kommen, lautet der Befehl:

docker-compose exec nextcloud_db mysql "-uroot" "-ptheboss"

Praxisbeispiel: Nextcloud und Zammad

Als Beispiel zeige ich zwei Anwendungen, die meine Kunden gerne verwenden, aber die nur unter Linux laufen. Während Nextcloud nur einen Webserver, PHP und MariaDB benötigt, ist Zammad wegen seiner vielen Abhängigkeiten nicht so einfach zu installieren. Ideal für Container also!

Nextcloud

Zuerst muss die Verzeichnisstruktur erstellt werden:

mkdir -p /nextcloud/mysql
mkdir -p /nextcloud/nextcloud

Danach erstellt man eine Datei mit Namen "docker-compose.yml" im Verzeichnis "/nextcloud" und fügt folgenden Inhalt ein:

version: '3'

services:
 nextcloud_db:
  image: mariadb
  restart: always
  volumes:
   - ./mysql:/var/lib/mysql
  environment:
   - MYSQL_ROOT_PASSWORD=theboss
   - MYSQL_USER=nextcloud
   - MYSQL_PASSWORD=onlyuser
   - MYSQL_DATABASE=nextcloud
  networks:
   - nextcloud_net

 nextcloud_web:
  image: nextcloud:apache
  restart: always
  networks:
   - nextcloud_net
  ports:
   - 8080:80
  volumes:
   - ./nextcloud:/var/www/html
  environment:
   - MYSQL_HOST=nextcloud_db
   - MYSQL_USER=nextcloud
   - MYSQL_PASSWORD=onlyuser
   - MYSQL_DATABASE=nextcloud
   - NEXTCLOUD_ADMIN_USER=admin
   - NEXTCLOUD_ADMIN_PASSWORD=iamadmin

networks:
 nextcloud_net:

Mittels "docker-compose up" werden ein Datenbank- und Web-Container erstellt. Diese befinden sich im gleichen virtuellen Netzwerk, wodurch sie sich gegenseitig sehen und über ihren Namen ansprechen können. Man muss sich also nicht um IP-Adressen kümmern. Port 8080 vom Host wird auf Port 80 des Web-Containers weitergeleitet. Wenn der Start abgeschlossen wurde, erreicht man Nextcloud unter http://host:8080.

Achtung: möglicherweise erscheint eine Fehlermeldung bezüglich "untrusted domain". Falls dies der Fall ist, muss man in der Datei "/nextcloud/nextcloud/config/config.php" den Namen oder die IP-Adresse, über welche man zugreift, eintragen:

'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => '192.168.1.10'
  ),

Zammad

Zammad habe ich im Beitrag https://nexcon.ch/2019/10/14/ein-ticketsystem-nur-fuer-it-firmen/ vorgestellt. Hier nun die Anleitung zum Betrieb als Container.

Als Voraussetzung muss auf dem Host das Limit für virtuellen Speicher erhöht werden:

sysctl -w vm.max_map_count=262144

Die Datei https://github.com/zammad/zammad-docker-compose/blob/master/docker-compose.yml im Verzeichnis "/zammad" speichern, bei "zammad-nginx" den Port "8081" auf "80" verknüpfen (wie bei Nextcloud Port "8080"). Zusätzlich die Datei https://github.com/zammad/zammad-docker-compose/blob/master/.env ins gleiche Verzeichnis herunterladen. Los gehts: aus dem Verzeichnis heraus "docker-compose up" starten.

Je nach Server dauert es ein paar Minuten, bis die Datenbanken initialisiert und alle Dienste gestartet wurden. Danach ist es geschafft und man kann auf Port 8081 auf sein Ticketsystem zugreifen.

Fazit

Das Container-Konzept und die vielen Befehle mögen auf den ersten Blick abschreckend wirken, aber eigentlich ist es nicht so schwierig. Wobei ich in diesem Beitrag nur die Spitze des Eisbergs zeigen konnte. Docker oder Tools wie Kubernets können in grossen Umgebungen eingesetzt werden, um tausende von Containern auf hunderten von Hosts zu betreiben.

Ein Gedanke zu „Container mit Docker in der Praxis

  1. Pingback: Traefik: der moderne Reverse Proxy - nexcon ag

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.