Steigern Sie Ihre Fähigkeiten mit diesem Docker Compose Tutorial

Wenn Sie sich fragen, wie Sie reproduzierbare Docker-Container mit Docker Compose erstellen können, sind Sie hier genau richtig. In diesem schrittweisen Docker Compose-Tutorial lernen Sie, wie Sie einfache Container erstellen, Ports mit Docker Compose zuordnen und komplexe Szenarien mit mehreren Containern erstellen können.

Sind Sie bereit? Dann legen wir los!

Voraussetzungen

Um diesem Tutorial Schritt für Schritt folgen zu können, stellen Sie sicher, dass Sie Folgendes haben:

  1. A fresh install of Ubuntu Server LTS with SSH Enabled. This guide will use Ubuntu Server LTS 20.04.1 as the Docker host machine.
  2. A computer with VS Code installed (optional). This guide will use Visual Studio Code 1.52.1 to SSH to the Docker host and run commands.
  3. Die offizielle SSH-Erweiterung von VS Code installiert und mit dem Docker-Host verbunden. (optional)

Was ist Docker Compose?

Einzeln Befehle können in Docker sehr lang werden. Nehmen Sie das folgende Beispiel. Dieses Beispiel erstellt einen Container für eine Softwareanwendung namens Bookstack.

docker create \
   --name=bookstack \
   -e PUID # UID des Benutzers, der Eigentümer der Anwendung/Dateien sein soll \
   -e PGID # GID des Benutzers, der Eigentümer der Anwendung/Dateien sein soll \
   -e DB_USER # Der Datenbankbenutzer \
   -e DB_PASS # Das Datenbankpasswort \
   -e DB_HOST # Der Datenbankhost \
   -e DB_DATABASE # Die zu verwendende Datenbank \
   -e APP_URL # Die URL, über die auf Ihre Anwendung zugegriffen wird (erforderlich für den korrekten Betrieb eines Reverse Proxys) \
   -v /host/path/to/config:/config # Speicherort für hochgeladene Daten \
   -p 80:80/tcp # Web UI Port \
   --restart unless-stopped \
   linuxserver/bookstack:version-v0.31.4

Je komplexer eine Docker-Umgebung wird, desto mehr Flags und Bedingungen sind für eine funktionierende Container-Einrichtung erforderlich. Die Docker-Befehlszeile wird immer umständlicher und schwieriger zu debuggen, insbesondere wenn mehrere Container eingesetzt werden.

Docker Compose ist eine Möglichkeit, reproduzierbare Docker-Container mithilfe einer Konfigurationsdatei anstelle von extrem langen Docker-Befehlen zu erstellen. Durch die Verwendung einer strukturierten Konfigurationsdatei lassen sich Fehler einfacher erkennen und Container-Interaktionen leichter definieren.

Docker Compose wird besonders wertvoll bei der Verwaltung von Container-Abhängigkeiten oder in Umgebungen mit mehreren Containern.

Docker Compose ist eine fantastische Möglichkeit, in die Infrastruktur als Code einzusteigen, ohne die Komplexität verteilter Systeme wie Kubernetes.

Docker Compose verwendet eine Konfigurationsdateistruktur namens YAML. YAML ist ähnlich wie JSON oder HTML aufgebaut, da YAML eine strukturierte, maschinenlesbare Sprache ist. YAML konzentriert sich speziell darauf, so gut lesbar wie möglich zu sein, während es gleichzeitig über strukturierte Leistung verfügt.

YAML hat jedoch den Nachteil, dass Leerzeichen und andere Leerzeichen wesentlich sind und korrekt formatiert werden müssen. VS Code erledigt einen Großteil dieser Arbeit für Sie und deshalb werden Sie viele Beispiele in VS Code sehen.

Installation von Docker Compose

Jetzt geht es darum, Ihre Hände schmutzig zu machen. Nehmen wir an, Sie sind mit Ihrem Docker-Host verbunden, dann ist es Zeit, Docker Compose zu installieren.

Docker Compose ist ein separates Paket von der Docker-Laufzeitumgebung. Aber die Installation von Docker Compose installiert auch die Docker-Laufzeitumgebung, so dass Sie zwei Fliegen mit einer Klappe schlagen!

Um Docker Compose und die Docker-Laufzeitumgebung zu installieren, führen Sie die folgenden beiden Befehle aus.

# Aktualisieren Sie die Softwareliste (bekannt als Repository) und installieren Sie dann Docker Compose
# mit allen benötigten Abhängigkeiten. Die -y-Flagge wird verwendet, um die Bestätigung zu überspringen
sudo apt update -y
sudo apt install docker-compose -y
The installation command for Docker Compose

Nach der Installation sollten Sie eine Ordnerstruktur erstellen, um Container zu speichern.

Erstellen einer Ordnerstruktur für Docker Compose

Bevor Sie mit Docker Compose einen Container erstellen können, sollten Sie zuerst einen Ordner zum Speichern der Container erstellen. Sie sollten nicht nur eine Ordnerstruktur zum Speichern von Containern erstellen, sondern Sie werden feststellen, dass verschiedene Docker-Befehle sensibel auf den Speicherort verschiedener Konfigurationsdateien reagieren; Docker Compose ist da keine Ausnahme.

Die wichtigste Komponente von Docker Compose ist die Konfigurationsdatei mit dem Namen docker-compose.yaml. Diese Konfigurationsdatei legt fest, wie die Docker-Laufzeitumgebung einen Container erstellen soll, wie oben erklärt.

Wenn Sie Docker Compose ausführen, sucht der Befehl nach seiner Konfigurationsdatei im selben Ordner, in dem der Befehl ausgeführt wird. Aufgrund dieser Anforderung ist es immer am besten, einen separaten Ordner zu erstellen, wenn Docker Compose ausgeführt wird.

In einem Ordner kann nur eine Docker Compose-Konfigurationsdatei vorhanden sein.

Zur Demonstration der Erstellung eines Docker-Containers mit Docker Compose erstellen Sie zuerst eine Ordnerstruktur zum Speichern des zukünftigen Containers und seiner Konfigurationsdatei mit einem kleinen Dateiserver namens Caddy.

Caddy ist ein Dateiserver, ähnlich wie Apache httpd oder Nginx, jedoch in der Programmiersprache Go geschrieben. Caddy ist speziell für eine einfache Verwendung ausgelegt (und generiert oder serviert automatisch eine index.html-Datei) ohne Konfiguration. Diese Kombination macht Caddy zu einer guten Wahl für Anfänger.

Angenommen, Sie sind auf Ihrem Docker-Host angemeldet, erstellen Sie die Ordnerstruktur wie folgt:

  1. Erstellen Sie in Ihrem Home-Verzeichnis einen Ordner mit dem Namen containers. Dieser Ordner dient als Platzhalter für diesen und andere Container.
  2. Erstellen Sie im Ordner containers einen Unterordner mit dem Namen caddy. Dieser Ordner enthält die Docker Compose-Konfigurationsdatei und den Caddy-Container selbst.
  3. Schließlich erstellen Sie innerhalb des Ordners caddy einen leeren Textdatei mit dem Namen docker-compose.yaml, die zur Docker Compose-Konfigurationsdatei wird.

Mit der erstellten Ordnerstruktur und der Docker Compose-Konfigurationsdatei können Sie nun beginnen, diese Konfigurationsdatei mit einer Docker Compose-Konfiguration zu füllen.

Erstellen einer Docker Compose-Konfigurationsdatei

In ihrer grundlegendsten Form sieht eine docker-compose.yaml-Datei für den Caddy-Container wie folgt aus. Kopieren und fügen Sie den unten stehenden Code in die zuvor erstellte Docker Compose-Konfigurationsdatei ein, entweder in Ihrem bevorzugten Linux-Texteditor oder mit VS Code.

version: "3.7"
services:
  caddy:
    container_name: "caddy"
    image: "caddy:latest"
    ports:
      - "80:80"

Gehen wir die gezeigten Optionen durch:

  • version gibt die Version der docker-compose-Datei an. Jede neue Definition von Docker Compose enthält Änderungen, die die Spezifikation brechen. Daher ist die Version wichtig, damit Docker Compose erkennen kann, welche Funktionen es verwenden muss. Version 3.7 ist die neueste Version, die von Ubuntu 20.04.1 LTS unterstützt wird.

Die vollständige Spezifikation für Docker Compose 3.x finden Sie hier. Die verlinkte Dokumentation enthält Informationen zu jeder einzelnen Option, die Sie in Docker Compose verwenden können.

  • services enthält die Spezifikationen für die eigentlichen Container. Sie können mehrere Container in diesem Abschnitt definieren.
  • caddy ist der Name des ersten Containers (dies dient nur als Referenz).
  • container_name definiert den tatsächlichen Namen, der dem Container von Docker gegeben wird, und muss eindeutig sein.
  • image ist der Name des Images. In diesem Fall wird caddy aus dem Docker Hub definiert. Der Name oder die Nummer nach dem mit einem Doppelpunkt getrennten Tag ist die Version.

Port-Mapping

Diese letzte Option erfordert besondere Erwähnung:

ports:
  - "80:80"

In Docker Compose ermöglicht die Anweisung ports das Festlegen einer oder mehrerer Zuordnungen vom Host zum Container. In dem obenstehenden Beispiel wurde beispielsweise der Port 80 auf dem Host auf den Port 80 im Container abgebildet. Es ist jedoch nicht erforderlich, die Portnummer anzupassen. Das folgende Beispiel bildet den Port 8800 auf dem Host auf den Port 80 im Container ab.

ports:
  - "8800:80"

Sie können auch mehrere Ports wie unten definiert angeben.

ports:
  - "80:80"
  - "443:443"

Dadurch werden sowohl der Port 80 als auch 443 auf dem Host abgebildet (eine häufige Konfiguration für Webserver, um sowohl HTTP als auch HTTPS anzubieten).

Der Ersteller des Docker-Images definiert die verfügbaren Ports zum Zeitpunkt der Erstellung. Überprüfen Sie unbedingt die Dokumentation des Images, mit dem Sie arbeiten, auf Docker Hub oder auf der Website des Maintainers, um die zuordenbaren Ports zu finden. Es macht keinen Sinn, einen Port abzubilden, wenn der Port nicht genutzt wird!

In Anbetracht dessen sehen wir uns nun an, wie der Container tatsächlich ausgeführt wird.

Container ausführen

Zu diesem Zeitpunkt sollten Sie die Datei docker-compose.yaml im Ordner ~\containers\caddy haben. Jetzt ist es an der Zeit, den Caddy-Container zu erstellen und zu starten.

Führen Sie im Terminal den folgenden Befehl aus, um die in der Datei docker-compose.yaml definierten Docker-Container zu starten.

# Dieser Befehl muss im selben Ordner wie die Datei ausgeführt werden. Die -d-Option führt
# den Befehl *detachiert* aus, wodurch der Container im Hintergrund gestartet wird
sudo docker-compose up -d

Sie werden feststellen, dass Sie bei der Ausführung des Befehls sudo docker-compose up -d den Speicherort der docker-compose.yaml-Datei nicht angeben mussten. Docker Compose erwartet, dass Sie alle Befehle im Ordner ausführen, der die docker-compose.yaml-Datei enthält, da viele Befehle relativ zu diesem Ordner sind.

Überprüfen Sie nun, ob der Container läuft, indem Sie zu http://<Ihre IP> navigieren. In diesem Leitfaden wird http://homelab-docker als Referenz verwendet.

Sie können diese Verarbeitung in VS Code sehen, während Sie über SSH mit dem Docker-Host verbunden sind, wie in der folgenden Animation dargestellt:

Demonstrating a container created with Docker Compose

Erfolg! Sie haben Docker Compose erfolgreich verwendet, um einen Container aus einer Konfigurationsdatei zu starten. Mit diesem wichtigen ersten Schritt werfen wir nun einen Blick darauf, wie Sie den Zustand Ihres Containers verwalten können.

Befehle zum Verwalten von abgetrennten Containern

In dem vorherigen Abschnitt haben Sie den Caddy-Container mit der Option -d gestartet. Dadurch wurde ein Container im abgetrennten Zustand ausgeführt. Wenn ein Container im abgetrennten Zustand ist, wird er im Hintergrund weiter ausgeführt. Dies stellt jedoch ein Problem dar: Wie verwalten Sie diesen Container, wenn Sie keine direkte Kontrolle mehr haben?

Um dieses Problem zu lösen, verfügt Docker Compose über eine Reihe von Befehlen, mit denen Container verwaltet werden können, die mit einer docker-compose.yaml-Datei gestartet wurden:

  • docker-compose restart wird verwendet, um einen Container neu zu starten, der derzeit läuft. Dabei handelt es sich um etwas anderes als docker-compose up -d erneut ausführen. Der Neustart-Befehl wird einfach einen vorhandenen Container neu starten, den Befehl docker-compose up -d erneut ausführen und den Container neu erstellen (wenn die Konfigurationsdatei geändert wurde).
  • docker-compose stop stoppt einen laufenden Container, ohne den Container zu zerstören. Ebenso startet docker-compose start den Container erneut.
  • docker-compose down beendet die laufenden Container und zerstört sie auch. Dabei spielt die Verwendung von Bind-Mounts von Volumes eine Rolle (weitere Informationen finden Sie unten).
  • docker-compose pull lädt die aktuelle Version des Docker-Images (oder der Images) aus dem Repository herunter. Wenn Sie den Tag latest verwenden, können Sie anschließend docker-compose down && sudo docker-compose up -d ausführen, um den Container durch die neueste Version zu ersetzen. Die Verwendung von docker-compose pull ist eine bequeme Möglichkeit, Container schnell mit minimaler Ausfallzeit zu aktualisieren.
  • docker-compose logs zeigt die Protokolle des laufenden (oder gestoppten) Containers an. Sie können auch einzelne Container ansprechen (wenn mehrere Container in der Compose-Datei definiert sind) mit docker-compose logs <Containername>.

A full list of docker-compose commands can be seen by running docker-compose with no additional arguments or referenced here in the documentation.

Jetzt, da Sie einen laufenden Container haben, schauen wir uns an, wie Sie lokal gespeicherten Inhalt auf Ihrer Maschine verwenden können.

Erstellung von Bind-Mounts in Docker Compose

Bind Mounts sind die Art und Weise, wie Docker wichtige Benutzerdaten auf den lokalen Speicher Ihres Servers abbildet. Um zu beginnen, generieren Sie Inhalte, die der Container hosten soll:

  1. Auf dem Docker-Host, innerhalb des Ordners ~/containers/caddy, erstellen Sie einen neuen Ordner namens files.

2. Erstellen Sie eine neue Datei namens index.html im Ordner ~/containers/caddy mit dem folgenden Inhalt. Dies wird die Hauptseite sein, die der Caddy-Webserver bereitstellt.

<body><h2>hello world!</h2></body>

3. Passen Sie Ihre Docker Compose-Konfigurationsdatei wie folgt an. Das unten stehende Beispiel fügt den Abschnitt volumes hinzu und verweist auf einen Bind-Mount zum gerade erstellten files-Ordner, um ihn dem Container zugänglich zu machen.

version: "3.7" services: caddy: container_name: "caddy" image: "caddy:latest" ports: - "80:80" volumes: #das ./ bezieht sich auf einen Ordner relativ zur docker-compose-Datei - "./files:/usr/share/caddy"

4. Führen Sie erneut docker-compose up -d aus. Docker Compose erkennt nun, dass die Datei geändert wurde, und erstellt Ihren Container neu.

5. Navigieren Sie mit einem Browser zur Seite des Containers, und Sie sollten nun sehen, dass die „Hello World!“-Seite bereitgestellt wird.

Sie können Folgendes in der unten stehenden Animation sehen:

Creating a bind mount using Docker Compose

Sie hosten jetzt Inhalte, die lokal auf Ihrem Gerät gespeichert sind! Was ist jedoch, wenn Ihre Inhalte von einer externen Quelle wie einem Netzwerkfreigabe stammen?

Verwendung von Docker Compose mit Docker-Volumes

Sobald Sie einen einfachen Container mit Docker Compose erstellt haben, müssen Sie wahrscheinlich darauf zugreifen, dass der Container möglicherweise auf eine andere Stelle, beispielsweise auf einen Netzwerkfreigabe, zugreift. In diesem Fall können Sie den Container so konfigurieren, dass er Docker-Volumes direkt in Ihrer Docker Compose-Konfigurationsdatei verwendet.

Zu Demonstrationszwecken wird in diesem Leitfaden ein Network File Share (NFS)-Server auf dem Docker-Host erstellt. Das Bereitstellen lokaler Inhalte als NFS-Mount hat außerhalb der Demonstration keinen praktischen Zweck. Wenn Sie ein NFS-Volume mounten möchten, stammt es in der Regel von einer externen Quelle wie einem NAS oder einem Remote-Server.

Einrichten einer NFS-Freigabe

Wenn Sie noch keine NFS-Freigabe eingerichtet haben, richten Sie diese jetzt auf dem Docker-Host für dieses Tutorial ein. Gehen Sie dazu wie folgt vor:

  1. Installieren Sie das Paket NFS-Server, indem Sie apt install nfs-kernel-server -y ausführen.

2. Fügen Sie den Container als NFS-Export hinzu (ähnlich wie eine Windows CIFS-Freigabe), indem Sie Folgendes ausführen.

# Fügen Sie der Konfigurationsdatei /etc/exports eine Zeile hinzu, um eine NFS-Freigabe für # /home/homelab/containers zu erstellen. Diese Freigabe ist nur für den Localhost zugänglich (um # anderen Computern den Zugriff zu verhindern) echo '/home/homelab/containers localhost(rw,sync,no_root_squash,no_subtree_check)' | sudo tee -a /etc/exports # Starten Sie den NFS-Server mit der neuen Konfiguration neu sudo systemctl restart nfs-kernel-server

3. Überprüfen Sie nun, ob der Host den NFS-Share freigibt, indem Sie den Befehl showmount -e localhost ausführen. Dieser Befehl zeigt alle derzeit freigegebenen NFS-Shares und deren Zugriffsberechtigungen an.

Im folgenden Screenshot sehen Sie, dass /home/homelab/containers freigegeben ist, aber nur für den Localhost-Computer (der auch der Server ist, auf dem der Docker-Host läuft).

Creating a NFS share in Ubuntu 20.04

Wenn Sie den Ordner /home/<Benutzername>/containers in der Ausgabe sehen, ist der NFS-Share eingerichtet.

Definieren eines benannten Docker-Volumes

Nachdem Sie den NFS-Share erstellt haben, müssen Sie Docker mitteilen, wie auf diesen Share zugegriffen werden soll. Mit Docker Compose können Sie dies tun, indem Sie ein benanntes Volume in der Docker Compose-Konfigurationsdatei definieren.

A named volume is a way for Docker to abstract network-based file shares. Network file sharing comes in all sorts of shapes and sizes these days: CIFS (windows) shares, NFS (Linux) shares, AWS S3 Buckets, and more. By creating a Named Volume, Docker does the hard part of figuring out how to talk to the network share and lets the container just treat the share as if it is local storage.

Um ein benanntes Volume zu erstellen:

  1. Öffnen Sie die Docker Compose-Konfigurationsdatei (docker-compose.yaml). Wenn Sie dem Beispiel folgen, sollte sich die Datei im Ordner ~/containers/caddy befinden.

2. Fügen Sie innerhalb der Docker Compose-Konfigurationsdatei nach dem Abschnitt services einen Abschnitt volumes hinzu. Ihre Konfigurationsdatei sollte wie folgt aussehen. Der Abschnitt volumes erstellt ein benanntes Volume namens MyWebsite. Innerhalb dieses benannten Volumes werden die erforderlichen Parameter (wie IP, NFS-Einstellungen und Pfad) angegeben. Der volumes-Parameter innerhalb des services-Abschnitts wird ebenfalls geändert, um auf das benannte Volume anstelle eines lokalen Ordners zu verweisen.

version: "3.7"
 services:
   caddy:
     container_name: "caddy"
     image: "caddy:latest"
     ports:
       - "80:80"
     volumes:
       - "MyWebsite:/usr/share/caddy"
 volumes:
   MyWebsite:
     driver_opts:
       type: "nfs"
       o: "addr=localhost,nolock,soft,rw"
       device: ":/home/homelab/containers/caddy/files"

3. Sobald Sie das benannte Volume definiert haben, das auf den NFS-Share im Docker Compose-Konfigurationsfile verweist, führen Sie docker-compose up -d aus, um den Container zu erstellen und zu starten. Wenn alles gut läuft, sollte der Container und die Website wieder hochfahren.

Setting NFS client settings within Docker Compose in VS Code

4. Navigieren Sie erneut zur Seite des Containers. Der Inhalt der index.html sollte genauso erscheinen, als ob die Datei lokal eingebunden würde. Allerdings wird diese Datei über den NFS-Server im Netzwerk eingebunden.

Demonstrating access to the index.html file through an NFS share in Docker

Da Sie nun externe Docker-Volumes in Docker Compose einbinden können, können Sie jetzt allerlei Netzwerkspeicher in Ihre Container bringen. Docker Compose kann jedoch mehr als nur einzelne Container oder Volumes definieren. Tauchen wir in komplexere, mehrere Container umfassende Szenarien ein.

In diesem Tutorial wird der Caddy-Container nicht mehr verwendet, daher können Sie den Container mit docker-compose down entfernen.

Definition mehrerer Container in Docker Compose

Die meisten Docker-Container funktionieren nicht isoliert. Docker-Container haben normalerweise Service-Abhängigkeiten wie Datenbanken oder separate Web-Services, die über eine API kommunizieren.

Mit Docker Compose können Sie Container in einer einzigen Datei gruppieren. Durch die Definition mehrerer Container in einer Datei können die Container zwischen abhängigen Services kommunizieren und die Organisation komplexer Container-Layouts vereinfachen.

Um ein solches Szenario zu demonstrieren, richten wir eine beliebte Wiki-Anwendung namens BookStack ein.

BookStack ist eine beliebte Wiki-Software, die für ihre Benutzerfreundlichkeit und hierarchische Struktur bekannt ist (im Gegensatz zu einer flachen Struktur wie bei Mediawiki).

BookStack, wie viele Webanwendungen, erfordert eine separate Datenbank, um ordnungsgemäß funktionieren zu können, sowie die Informationen, die zum Kommunizieren mit der Datenbank benötigt werden. Die Einrichtung einer solchen Situation ist eine Stärke von Docker Compose.

Erstellen Sie die Docker Compose-Konfigurationsdatei

BookStack hat kein intern gepflegtes Docker-Image, jedoch stellt linuxserver.io ein renommiertes Docker Hub-Image im Auftrag von BookStack bereit. Während die Dokumentation auf der Docker Hub-Website eine empfohlene Docker Compose-Konfigurationsdatei enthält, wird in diesem Tutorial eine neue Konfigurationsdatei erstellt und dabei die Konzepte erläutert.

Auf dem Docker-Host:

  1. Erstellen Sie zunächst einen Ordner für BookStack. Wenn Sie den vorherigen Abschnitten gefolgt sind, sollten Sie einen Ordner namens ~/containers haben. Erstellen Sie darin einen Ordner namens bookstack.

2. Erstellen Sie dann eine leere Docker Compose-Konfigurationsdatei namens docker-compose.yaml im Ordner bookstack.

Creating the folder structure for Bookstack in VS Code

3. Öffnen Sie nun die Docker Compose-Konfigurationsdatei und definieren Sie zwei Container: den bookstack-Container und den bookstack_db (mariadb)-Container.

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"

Bisher verwendet die Datei docker-compose.yaml größtenteils bereits eingeführte Konzepte: Sie haben zwei Dienste (bookstack und bookstack_db), beide mit Abbildungen und Bind-Mounts. Der Bookstack-Container hat ein Port-Mapping vom Host-Port 8080 zum internen Port 80.

Aufgrund des äußerst geringen Overheads von Docker-Containern ist es üblich, für jede Webanwendung einen separaten Datenbankcontainer zu definieren. Dadurch wird eine größere Trennung der Aufgaben ermöglicht. Dies unterscheidet sich deutlich von herkömmlichen Datenbank-Setups, bei denen eine einzelne Datenbankinstallation Hunderte von Webanwendungen bedienen kann.

In der obigen Datei sehen Sie eine neue Option, den Befehl depends_on. Dieser Befehl gibt Docker die Reihenfolge vor, in der die Container gestartet werden sollen. Durch die Definition des depends_on-Befehls teilen Sie Docker mit, dass der bookstack_db-Container zuerst starten muss.

Aufbau der Container-Kommunikation mit Umgebungsvariablen

Diese in den letzten Abschnitten erstellte Konfigurationsdatei ist noch nicht vollständig. Obwohl Sie zwei Dienste (Container) definiert haben, kommunizieren sie nicht miteinander! Der bookstack-Container weiß nicht, wie er mit dem bookstack_db-Container kommunizieren soll. Lassen Sie uns das mit Hilfe von Umgebungsvariablen lösen.

Umgebungsvariablen sind die gängigste Methode, um Variablen an Docker-Container bereitzustellen. Diese Variablen werden zur Laufzeit übergeben (oder in der docker-compose.yaml-Konfigurationsdatei definiert), um Informationen darüber bereitzustellen, was der Container tun soll.

Umgebungsvariablen werden von der Person definiert, die das Docker-Image erstellt. Sie werden je nach verwendetem Docker-Image unterschiedlich sein, und Sie müssen sich auf die Dokumentation des Erstellers beziehen, um herauszufinden, welche Umgebungsvariablen verwendet werden sollen.

Es gibt zwei Methoden zur Definition von Umgebungsvariablen: direkt in der docker-compose.yaml-Datei selbst oder als separate Datei.

A separate file is, typically, the recommended method, especially if variables contain sensitive data such as passwords. A docker-compose.yaml file is designed to be shared or even uploaded to a public-facing GitHub repo. Having a separate file for sensitive data reduces the chance of an accidental security breach.

Erstellen Sie auf dem Docker-Host nun zwei Umgebungsvariablen: eine für den bookstack-Container und eine für den bookstack_db-Container.

  1. Erstellen Sie eine neue Datei im Ordner ~/containers/bookstack mit dem Namen bookstack.env und folgendem Inhalt:
APP_URL is the IP address or hostname of your server. This article is using homelab-docker
 APP_URL=http://homelab-docker:8080
 DB_HOST is the container name you gave your container
 DB_HOST=bookstack_db
 DB_USER is defined in the bookstack_DB environment file
 DB_USER=bookstack_user
 DB_PASS is also defined in the bookstack_DB environment file
 DB_PASS=MySecurePassword
 DB_DATABASE is the name of the database within mariadb
 DB_DATABASE=bookstack

2. Erstellen Sie eine neue Datei im Ordner ~/containers/bookstack mit dem Namen bookstack_db.env und folgendem Inhalt:

The root password for our database, keep it secret, keep it safe
 MYSQL_ROOT_PASSWORD=MySecureRootPassword
 The database bookstack will be using
 MYSQL_DATABASE=bookstack
 the user bookstack will be using
 MYSQL_USER=bookstack_user
 the password bookstack will be using
 MYSQL_PASSWORD=MySecurePassword

3. Als bewährte Methode stellen Sie sicher, dass beide env-Dateien für andere Benutzer nicht lesbar sind.

chmod 600 bookstack.env bookstack_db.env

Sie sollten den Lesezugriff ändern, da sowohl die Dateien bookstack.env als auch bookstack_db.env sensible Daten enthalten.

4. Aktualisieren Sie die Docker Compose-Datei ~/containers/bookstack/docker-compose.yaml, um auf diese beiden Umgebungsdateien zu verweisen, wie unten gezeigt.

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
     env_file:
       - "./bookstack.env"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"
     env_file:
       - "./bookstack_db.env"

5. Starten Sie nun die Container bookstack und bookstack_db mit Docker Compose.

sudo docker-compose up -d

Sie können jeden der oben genannten Schritte in diesem Abschnitt in VS Code sehen.

Setting up environment variables and the Docker Compose file with VS Code

Überwachen der Docker Compose-Protokolle

Der Docker-Engine arbeitet mit Docker Compose zusammen, um viele verschiedene Aufgaben im Hintergrund auszuführen. Es ist hilfreich, überwachen zu können, was gerade passiert, insbesondere wenn man mit mehreren Containern gleichzeitig arbeitet.

Um beispielsweise den Bookstack-Container zu überwachen, verwenden Sie den Befehl logs. In diesem Tutorial können Sie, sobald Sie die Logs sehen, die [services.d] done anzeigen, zur Bookstack-URL gehen.

sudo docker-compose logs bookstack
Using the docker-compose logs command
The bookstack welcome screen. Default login is [email protected]/password

Zu diesem Zeitpunkt sollten Sie einen voll funktionsfähigen Wiki haben, das in seinem eigenen Container mit seiner eigenen Datenbank vollständig in Docker läuft!

Solange Sie die Bookstack- und Bookstack_db-Ordner haben, können Sie Ihre Bookstack-Umgebung von Grund auf neu erstellen.

Docker Compose und Netzwerk

Bis jetzt haben Sie nicht viel über die Kommunikation und das Netzwerkverhalten von Containern gelernt. Das wollen wir ändern.

Wenn Sie mehrere Container in einer einzigen docker-compose.yaml-Datei erstellen, wie Sie es in den vorherigen Abschnitten getan haben, werden sie alle demselben Netzwerk zugewiesen (normalerweise name-of-parent-folder_default genannt).

Sie können das Netzwerk, das für die Container erstellt wurde, sehen, wenn Sie docker-compose up -d ausführen, wie unten gezeigt.

The default network created with docker-compose comes up

Wenn alle Container demselben Netzwerk zugewiesen werden, erstellt Docker intern DNS-Einträge für sie. Deshalb haben Sie in dem vorherigen Beispiel Ihre Datenbank als bookstack_db in den Umgebungsvariablen bezeichnet. Dieser Name bookstack_db ist tatsächlich ein DNS-Eintrag, der auf die IP-Adresse des Datenbank-Containers verweist.

Sie müssen sich auch nicht auf Docker Compose verlassen, um Netzwerke automatisch zu generieren. Sie können interne oder externe Netzwerke manuell definieren. Die manuelle Definition von Netzwerken ist großartig, wenn Sie einen Container haben, der mit einem anderen Container in einer separaten docker-compose.yaml-Datei kommunizieren muss. Sie könnten die Ports freigeben oder ein Netzwerk erstellen, dem beide beitreten können!

Beachten Sie, dass Sie, wenn Sie Netzwerke explizit definieren, auch das Standardnetzwerk explizit definieren müssen. Docker Compose wird das automatische Erstellen dieses Netzwerks einstellen, sobald Sie mit der Definition der Netzwerke beginnen.

Ändern Sie nun die docker-compose.yaml von BookStack, um ein extern erstelltes Netzwerk einzuschließen.

  1. Erstellen Sie das externe Netzwerk mit dem Befehl docker network create my_external_network.

2. Definieren Sie das externe Netzwerk in der docker-compose.yaml.

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
     env_file:
       - "./bookstack.env"
     networks:
       - "my_external_network"
       - "bookstack_default"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"
     env_file:
       - "./bookstack_db.env"
     networks:
       - "bookstack_default"
 networks:
   bookstack_default:
   my_external_network:
     external: true

3. Führen Sie docker-compose up -d aus, um die Container neu zu erstellen. Ihre beiden Container sind nun mit zwei Netzwerken verbunden, wie unten gezeigt.

A highlight of the networks defined within a docker-compose file

Der BookStack-Container ist nun auch mit einem extern definierten Netzwerk verbunden. Dies ermöglicht es Ihnen, einen weiteren Container zu erstellen, der den BookStack-HTTP-Verkehr in HTTPS umwandelt, bevor er Docker verlässt (auch als Reverse-Proxy bezeichnet).

Festlegen eines bestimmten Benutzers zum Ausführen eines Containers.

Standardmäßig werden alle Docker-Container als abgeschotteter Root-Benutzer ausgeführt. Dies entspricht dem Ausführen einer virtuellen Maschine als Standardadministratorbenutzer. Obwohl dies im Allgemeinen kein Problem ist, bestehen Sicherheitsbedenken, wenn die Sandbox kompromittiert ist.

Ein weiteres Problem bei der Ausführung als Root-Benutzer sind Dateiberechtigungen. Möglicherweise stellen Sie fest, dass Sie den Ordner db innerhalb des Ordners bookstack nicht löschen können, da der Inhalt im Besitz von Root ist.

Obwohl die meisten Abbilder das Ausführen als Nicht-Root-Benutzer nicht unterstützen, bieten linuxserver.io-Abbildungen insbesondere eine Umgebungsvariable zum Festlegen des Benutzers, der innerhalb des Containers ausgeführt wird. Sie können dies tun, indem Sie UID=1000 und GID=1000 in die Konfiguration bookstack.env hinzufügen.

1000:1000 ist die Standard-Benutzer-ID und Gruppe für den ersten Benutzer in Ubuntu (was möglicherweise nicht Sie sind). Weitere Informationen zu Benutzer-IDs und Gruppen-IDs finden Sie unter Verwandt: Ein Windows-Guy in einer Linux-Welt: Benutzer und Dateiberechtigungen)

Sie können auch eine UID und GID mit dem user-Parameter in Docker-Compose erzwingen, dies wird jedoch nicht empfohlen, da die meisten Container sich nicht gut verhalten, wenn sie auf einen anderen Benutzer gezwungen werden

Einstellen der Neustart-Richtlinie

Wenn Sie möchten, dass mit Docker Compose erstellte Container bei einem Ausfall neu gestartet werden, verwenden Sie die restart-Richtlinie, indem Sie einen restart: <option>-Parameter unter den Container-Einstellungen in der docker-compose.yaml hinzufügen.

restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

Das Hinzufügen dieses Parameters bewirkt, dass Container bei einem Ausfall automatisch neu gestartet werden, um die Betriebszeit im Falle unerwarteter Stromausfälle aufrechtzuerhalten.

Manuelles Festlegen von DNS-Einträgen für Container

Ähnlich wie bei Windows und Linux verfügt Docker auch über eine „hosts“-Datei. Mit dem extra_hosts-Parameter in einer Konfigurationsdatei können Sie einen Host erzwingen, der sich in eine bestimmte IP auflöst. Dies kann nützlich sein, wenn Sie DNS-Einschränkungen haben, wie z.B. Split-DNS oder einen Testserver, mit dem Sie vorübergehend interagieren möchten.

extra_hosts:
  - "somehost:x.x.x.x"
  - "otherhost:x.x.x.x"

Ausführen von Befehlen

Nachdem der Container gestartet ist, können Sie Befehle innerhalb des Containers mit dem Befehl docker-compose run ausführen. Möglicherweise möchten Sie beispielsweise ein Bash-Terminal in Ihrem bookstack-Container starten. Dazu führen Sie den folgenden Befehl aus.

docker-compose run web bash

Schlussfolgerung

Zu diesem Zeitpunkt sollten Sie genügend Informationen haben, um den meisten docker-compose-Tutorials im Web folgen zu können. Mit diesem Wissen können Sie Ihre Fähigkeiten erheblich erweitern, um in die Welt von Docker und dem Erstellen von Webanwendungen mit „Infrastructure as Code“ einzutauchen.

Source:
https://adamtheautomator.com/docker-compose-tutorial/