Docker – Teil 5: Docker Compose für mehrere Container

Nachdem wir uns nun etwas besser mit dem Dockerfile auskennen kommen wir zum nächsten Teil unserer kleinen Docker Einsteigerserie. Das Verlinken und Verwalten von mehreren Containern kann auf Dauer sehr anstrengend, unübersichtlich und schlecht dokumentierbar werden. Um dieses Problem zu lösen gibt es Docker Compose.

Mit Docker Compose lassen sich innerhalb einer einzigen Datei mehrere Container einstellen und ihre Beziehungen untereinander definieren. Danach können diese Container mit einem einzigen Befehl gestartet werden. Diese Datei könnt ihr dann (genau wie ein einzelnes Dockerfile) zum Beispiel mit Kollegen teilen und alle haben blitzschnell wieder dieselbe Serverumgebung ohne großartige Erklärungen welcher Container nun genau welchen Port wohin verlinken muss.

Container verlinken mit Docker Compose

Bevor wir uns kopfüber in die Funktionen von Docker Compose stürzen hier nochmal eine kleine Wiederholung warum wir verschiedene Container überhaupt verlinken müssen:

Ein Docker Container ist eine in sich abgeschlossene Einheit. Von Haus aus können weder Verbindungen nach drinnen noch nach draußen (wir erinnern uns an das Beispiel mit den Frachtcontainern). Oft ist es aber nötig, dass entweder mehrere Container untereinander kommunizieren müssen (beispielsweise ein Webserver mit einer Datenbank) oder ein Container mit dem Hostcomputer, auf dem er gestartet wurde, kommunizieren muss (beispielsweise um auf PHP Dateien zuzugreifen, die dort auf der Festplatte liegen).

Und genau hier kommt die Verlinkung ins Spiel. Diese ermöglicht uns, bestimmte Ports freizugeben um eine Verbindung von außen (also anderen Containern) zuzulassen oder eben auch ein bestimmtes (oder mehrere) Verzeichnis mit dem Hostsystem zu teilen. Bei zwei Containern ist das noch kein großer Aufwand. Aber stellen wir uns mal eine normale Webumgebung vor. Da haben wir:

  1. Den Webserver (zum Beispiel Nginx), der Zugriff auf die Website-Dateien (um sie auszuliefern) und eine Verbindung zu PHP (um Bescheid zu geben, welche Datei nun ausgeführt werden soll) benötigt
  2. PHP-FPM, welches sich darum kümmert, PHP Dateien auszuführen und die Ergebnisse an den Webserver zurückzuliefern. Dafür benötigt es Zugriff auf diese Dateien. Außerdem benötigt PHP auch noch eine Verbindung zur Datenbank um dort benötigte Daten abfragen zu können.
  3. Die Datenbank

Selbst hier wird es langsam schon anstregend, den Überblick über diese verschiedenen Tools zu behalten. Und je nach Anwendung kommen noch diverse andere Tools dazu, beispielsweise NodeJS, Cacheserver, Load Balancer und ähnliches. Ganz schön viel also. Gut, dass wir das ab sofort ganz simpel mit Docker Compose orchestrieren können.

 

 

docker-compose.yml

Das Herzstück von Docker Compose bildet eine YAML Datei namens docker-compose.yml. In dieser Datei definieren wir die Container, die wir starten wollen und ihre Beziehungen untereinander. Wir können Verzeichnisse mit dem Hostsystem teilen, Ports freigeben und Verlinkungen herstellen – und natürlich noch einiges mehr. In diesem Artikel beschränken wir uns aber erstmal auf die Basics.

In der ersten Ebene der Datei schreiben wir die Namen unserer einzelnen Container. Diese sind wichtig, da wir mit Hilfe dieser Namen auf andere Container referenzieren können (also beispielsweise verlinken). In der Unterebene zu jedem Container werden dann die einzelnen Eigenschaften durchgegangen, von denen wir als nächstes ein paar besprechen. Ein einfaches Beispiel dafür sieht so aus:

Mit diesem Beispiel könnten wir zwei Container gleichzeitig starten – und nichts sonst. Diese würden (je nachdem was die angegebenen Images machen) einfach fröhlich vor sich hin laufen. Laaaangweilig.

Machen wir die Sache ein wenig spannender und schauen uns ein paar Optionen an, die Docker Compose uns zur Verfügung stellt:

 

 

image

Fangen wir mit dem wichtigsten zuerst an – image. Mit der image Eigenschaft bestimmen wir, auf welchem Docker Image ein Container basieren soll. Docker sucht sich dafür das angegebene Image im Docker Hub, lädt es runter und startet es automatisch. Da viele moderne Tools (wie zum Beispiel Webserver etc) schon mit vorgefertigten Docker Images aufwarten können sparen wir uns dabei eine Menge Arbeit und müssen diese nicht erst selbst installieren.

 

build

Build ist das Gegenstück zu image (und die beiden sind auch exklusiv, es kann also nur eins von beidem für einen Container geben). Als Wert vergeben wir hier einfach den Pfad zu einem Dockerfile – relativ von unserem docker-compose.yml File aus gesehen – das beim Starten der Container ausgeführt werden soll. Da wir das für jeden einzelnen Container machen können haben wir die Möglichkeit, unsere „Containerfarm“ ganz auf unsere Wünsche anzupassen. Falls sich das Dockerfile im selben Verzeichnis wie die docker-compose.yml Datei befindet geben wir einfach einen . an. Falls das Dockerfile nicht genau so heißt können wir außerdem mit der Eigenschaft dockerfile den Namen ändern, der verwendet wird.

 

ports

Diese Eigenschaft ist ziemlich eindeutig benannt und sie macht auch genau das, was man erwarten würde. Ports öffnet die angegebenen Ports in unserem Container und verbindet sie mit einem Port auf dem Host. Dadurch können wir zum Beispiel dafür sorgen, dass zwei Programme, die denselben Port benutzen, auf demselben Server laufen. Wir weisen einfach dem einen Programm einen anderen Port auf dem Host zu als dem anderen.

Hier gibt es mehrere Schreibweisen:

  • Eine einzelne Zahl (zum Beispiel „8080“) öffnet einen einzelnen Port. Wird für den Host kein Port angegeben wird ein zufälliger bestimmt.
  • Mit Doppelpunkten getrennte Zahlen (zum Beispiel „8080:80“) mappen Ports vom Host (vor dem Doppelpunkt) in den Container (nach dem Doppelpunkt).
  • Mit Bindestrich getrennte Zahlen öffnen eine ganze Reihe von Ports (zum Beispiel „8001-8010“).

Diese Eigenschaft benötigen wir beispielsweise wenn wir Programme wie einen Webserver oder MySQL in einem Container laufen lassen. Die anderen Container benötigen Zugriff darauf, daher müssen wir die passenden Ports (zum Beispiel 80/443 für den Webserver oder 3306 für MySQL) freigeben.

 

 

volumes

Die volumes Eigenschaft gibt uns die Möglichkeit, ein Verzeichnis (oder auch mehrere) vom Host im Container verfügbar zu machen. Dafür geben wir einfach den Pfad auf dem Host an, wo das Verzeichnis zu finden ist. Außerdem können wir optional noch mit Doppelpunkt getrennt einen Pfad angeben, auf den das Verzeichnis im Container gemappt werden soll. Werden Änderungen auf einer Seite gemacht (also beispielsweise im Container) sind diese automatisch auch auf der anderen Seite (also auf dem Host). Das ist eine einfache Möglichkeit, Datenkonsistenz zu erhalten, denn normalerweise werden Daten, die in einem Container liegen, beim Zerstören des Containers gelöscht. Werden sie allerdings über ein solches Volume auf dem Hostrechner abgelegt bleiben sie auch beim Containerneustart erhalten.

 

volumes_from

Klingt sehr ähnlich wie die vorherige Eigenschaft – ist auch beinahe dasselbe. Volumes_from lässt uns alle Volumen, die wir in einem anderen Container haben, auch in diesen Container übernehmen. Das ist äußerst praktisch um immer Zugriff auf dieselben Daten zu haben. Das wird beispielsweise wichtig, wenn wir in einem Container einen Webserver und im anderen PHP laufen lassen. Beide benötigen Zugriff auf die PHP Dateien. Hier geben wir einfach den Namen des Containers an, so wie wir ihn in unserem docker-compose.yml vergeben haben.

 

links

Die links Eigenschaft ist wirklich hilfreich. Docker Compose erlaubt uns damit, einen Hosteintrag von einem Container in einem anderen zur Verfügung zu stellen. Müssen wir in einem Container also beispielsweise auf einen anderen zugreifen (beziehungsweise benötigen dessen IP Adresse in einer Konfiguration – beispielsweise bei PHP-FPM) können wir diesen Eintrag vergeben und können anstatt der IP Adresse einfach den Namen des Containers verwenden – Docker Compose kümmert sich um den Rest.

In diesem Beispiel hätten wir also die Möglichkeit, in unserer Nginxkonfiguration einfach den PHP-FPM Container mit dem Hostnamen myphp-fpm anzusprechen. Klasse!

 

 

Docker Compose Befehle

Nachdem wir unser docker-compose.yml File nun vorbereitet haben fehlt noch das Arbeiten damit – wie starten oder beenden wir nun die Container, die wir hier konfiguriert haben? Sehen wir uns noch ein paar Befehle an, die wir nun verwenden können, um unsere Container zu verwalten.

 

docker-compose up

Der erste Befehl ist docker-compose up. Genau wie beispielsweise vagrant up erzeugt und startet dieser Befehl einfach die Container, die wir in unserem YAML File definiert haben. Das bedeutet, wir können alle unsere Container mit diesem einen Befehl starten – super.

 

docker-compose build

Der docker-compose build Befehl baut alle Container zusammen und tagged diese dann, sodass sie beim nächsten Starten schneller verfügbar sind. Wenn sich also etwas in einem Buildverzeichnis oder einem Dockerfile ändert führen wir einfach diesen Befehl aus, um die Änderungen in unserer Docker Compose Umgebung mitzubekommen.

 

docker-compose ps

Genau wie docker ps listet auch docker-compose ps die aktiven Container auf, die von Docker Compose aktuell verwaltet werden.

 

docker-compose start / stop

Mit den Namen, die wir im docker-compose ps Befehl sehen können können wir einzelne Container mit Hilfe von docker-compose start / stop ganz einfach starten / stoppen.

 

docker-compose rm

Ebenfalls mit dem Namen können wir einen getaggten Container mit docker-compose rm auch wieder Entfernen. Führen wir danach docker-compose up aus wird dieser auch neu erzeugt.

 

 

Wie findest du Docker Compose? Kommt es auf deinen Servern schon zum Einsatz? Hast du vielleicht noch ein paar Tipps und Tricks, die hier fehlen? Hinterlass mir gerne einen Kommentar unter dem Artikel.

Schreibe einen Kommentar

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

*