Zum Inhalt springen

Skript/Linux/Docker

Aus Foxwiki
Version vom 3. November 2025, 17:51 Uhr von Dirkwagner (Diskussion | Beiträge) (Textersetzung - „Docker/Workshop“ durch „Docker“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Inhalt

Kapitel Beschreibung
1 Überblick
2 Docker/Grundlagen
3 Installation
4 Containerisieren
5 Aktualisieren
6 Datenbank
7 Mounts
8 Multi-Container
9 Compose
10 Image-Erstellung
11 Ausblick

1 Überblick

Docker - Isolierung von Anwendungen durch Container-Virtualisierung

Beschreibung

Schlanke Frorm der Virtualisierungen
  • Prozesse laufen auf dem Kernel des Host-Betriebssystems
  • Abschottung durch

Linzenz

Docker ist freie Software

Realisierung von Containern

Linux-Techniken
Schnittstellen, um auf Virtualisierungsfunktionen des Linux-Kernels zuzugreifen.


Begriffe

Begriff Beschreibung
Volume Volumes ermöglichen es, dass Daten erhalten bleiben, auch wenn ein Docker-Container gelöscht wird. Volumes sind auch eine praktische Möglichkeit, Daten zwischen dem Host und dem Container auszutauschen.
Image Ein Docker-Image ist eine schreibgeschützte Vorlage, die von der Docker-Engine benutzt wird, um einen Container zu erzeugen.

Speicherabbild eines Containers

  • Das Image selbst besteht aus mehreren Layern, die schreibgeschützt sind und somit nicht verändert werden können
  • Ein Image ist portabel, kann in Repositories gespeichert und mit anderen Nutzern geteilt werden
  • Aus einem Image können immer mehrere Container gestartet werden
Container Docker-Container sind isolierte Ausführungseinheiten für Anwendungen und ihre Abhängigkeiten

Aktive Instanz eines Images

  • Der Container wird also gerade ausgeführt und ist beschäftigt
  • Sobald der Container kein Programm ausführt oder mit seinem Auftrag fertig ist, wird der Container automatisch beendet
Layer Teil eines Images und enthält einen Befehl oder eine Datei, die dem Image hinzugefügt wurde
  • Anhand der Layer kann die ganze Historie des Images nachvollzogen werden
Dockerfile Beschreibung zur Erstellung eines Docker-Container
  • Textdatei, die mit verschiedenen Befehlen ein Image beschreibt
  • werden bei der Ausführung abgearbeitet und für jeden Befehl wird ein einzelner Layer angelegt
Repository Satz gleichnamiger Images mit verschiedenen Tags, zumeist Versionen
Registry Verwaltung von Repositories (Docker Hub, Artifactory, ...)

Bibliotheken

Begriff Beschreibung
libcontainer Schnittstelle zu den Grundfunktionen von Docker
libswarm Schnittstelle, um Docker-Container zu steuern
libchan Einfache („light weighted“) Kommunikation zwischen Prozessteilen und Prozessen

Aufbau und Funktionen

„Build, Ship and Run Any App, Anywhere“
"Bild: Virtuelle Maschinen und Docker-Container im Vergleich"
Während jede virtuelle Maschine ein eigenes Betriebssystem startet, teilen sich Docker-Container den Kernel des Host-Systems

Unter diesem Motto bewirbt die quelloffene Container-Plattform Docker eine flexible, ressourcensparende Alternative zur Emulation von Hardware-Komponenten auf Basis virtueller Maschinen (VMs)

  • Während die klassische Hardware-Virtualisierung darauf beruht, mehrere Gastsysteme auf einem gemeinsamen Host-System zu starten, werden Anwendungen bei Docker mithilfe von Containern als isolierte Prozesse auf ein und demselben System ausgeführt
  • Man spricht bei der containerbasierten Server-Virtualisierung daher auch von einer Operating-System-Level-Virtualisierung

Der Vorteil containerbasierter Virtualisierung liegt somit darin, dass sich Anwendungen mit unterschiedlichen Anforderungen isoliert voneinander ausführen lassen, ohne dass dafür der Overhead eines separaten Gastsystems in Kauf genommen werden muss

  • Zusätzlich können Anwendungen mit Container plattformübergreifend und in unterschiedlichen Infrastrukturen eingesetzt werden, ohne dass diese an die Hard- oder Software-Konfigurationen des Hostsystems angepasst werden müssen

Docker ist das bekannteste Software-Projekt, das Anwendern und Anwenderinnen eine auf Containern basierende Virtualisierungstechnologie zur Verfügung stellt

  • Die quelloffene Plattform setzt dabei auf drei grundlegende Komponenten: Um Container auszuführen, brauchen Anwender lediglich die Docker-Engine sowie spezielle Docker-Images, die sich über das Docker-Hub beziehen oder selbst erstellen lassen

Motivation

Vereinfachte Bereitstellung von Anwendungen
  • Container, die alle nötigen Pakete enthalten leicht als Dateien transportieren und installieren lassen
  • Geringerer Overhead durch geteilten Host-Kernel
  • Schnelle Start- und Stopzeiten
  • Hohe Dichte isolierter Instanzen pro Host
  • Prozess- und Abhängigkeitsisolation (Namespaces, cgroups)
  • Reproduzierbare Laufzeitumgebungen durch unveränderliche Images
  • Portabilität über unterschiedliche Hosts und Plattformen
  • Feingranulares Ressourcen- und Zugriffsmanagement
  • Vereinfachtes Lebenszyklus-Management
Container gewährleisten

Trennung und Verwaltung der auf einem Rechner genutzten Ressourcen

  • Code
  • Laufzeitmodul
  • Systemwerkzeuge
  • Systembibliotheken
  • alles was auf einem Rechner installiert werden kann

Container

Sandbox-Prozess

Ein Container ist ein Sandbox-Prozess, der auf einem Host-Computer ausgeführt wird und von allen anderen auf diesem Host-Computer ausgeführten Prozessen isoliert ist

  • Diese Isolierung nutzt Kernel-Namespaces und cgroups, Funktionen, die es in Linux schon seit langem gibt
  • Docker macht diese Funktionen zugänglich und einfach zu verwenden
  • Ein ist Container eine lauffähige Instanz eines Images
Container werden über die Docker-API oder die Befehlszeilenschnittstelle
  • erstellt
  • gestartet
  • angehalten
  • verschoben
  • gelöscht
Er kann auf lokalen oder virtuellen Maschinen ausgeführt oder in der Cloud bereitgestellt werden
  • Er ist portabel (und kann auf jedem Betriebssystem ausgeführt werden)
  • Er ist von anderen Containern isoliert und führt seine eigene Software, Binärdateien, Konfigurationen usw
Erweiterte Form von chroot
  • Das Dateisystem wird aus einem Image bereitgestellt
  • Allerdings bietet der Container eine zusätzliche Isolation, die mit chroot nicht möglich ist
Siehe auch

Bereitstellung

Image oder Dockerfile
  • Fertige Images
  • Dockerfiles
    • Anweisungen zum Erzeugen eines Images (Dockerfiles ) im Projekt verteilen
    • Dockerfiles können gut in Projekt-Repositoies bereitgestellt werden

Fertige Images

DockerHub bietet fertige Images

  • Ein solches gestartetes Image nennt sich dann Container und enthält beispielsweise Dateien, die in den Container gemountet oder kopiert werden
  • Man kann auch eigene Images bauen, indem man eine entsprechende Konfiguration (Dockerfile) schreibt
  • Jeder Befehl bei der Erstellung eines Images erzeugt einen neuen Layer, die sich dadurch mehrere Images teilen können

In der Konfiguration einer Gitlab-CI-Pipeline kann man mit image ein Docker-Image angeben, welches dann in der Pipeline genutzt wird

Docker Images

Ähnlich wie virtuelle Maschinen basieren Docker-Container auf Images

Schreibgeschützte Vorlage

Dieses isolierte Dateisystem wird von einem Image bereitgestellt, und das Image muss alles enthalten, was zur Ausführung einer Anwendung erforderlich ist - alle Abhängigkeiten, Konfigurationen, Skripte, Binärdateien und so weiter.

Portables Abbild eines Containers

Als wird ein Docker-Image in Form einer Textdatei beschrieben – man spricht von einem Dockerfile

  • Soll ein Container auf einem System gestartet werden, wird zunächst ein Paket mit dem jeweiligen Image geladen – sofern dieses nicht lokal vorliegt
  • Das geladene Image stellt das für die Laufzeit benötigte Dateisystem inklusive aller Parameter bereit
  • Ein Container kann als laufender Prozess eines Images betrachtet werden
Siehe auch

Docker-Engine

Mit Docker-Befehlen können Anwenderinnen und Anwender Software-Container direkt aus dem Terminal starten, stoppen und verwalten

  • Die Ansprache des Daemon erfolgt über das Kommando dockerund Anweisungen wie build (erstelle), pull (lade herunter) oder run (starte)
  • Client und Server können sich dabei auf dem gleichen System befinden
  • Alternativ steht Anwendern die Möglichkeit offen, einen Docker-Daemon auf einem anderen System anzusprechen
  • Je nachdem, welche Art von Verbindung aufgebaut werden soll, erfolgt die Kommunikation zwischen Client und Server über die REST-API, über UNIX-Sockets oder eine Netzwerkschnittstelle

Komponenten

Zusammenspiel der Docker-Komponenten

"Bild: Schematische Darstellung der Docker-Architektur"
Die Docker-Architektur basiert auf einem Zusammenspiel aus Client (Terminal), Server (Docker-Daemon) und Registry (Docker-Hub)
Beispiel
  • docker build
  • docker pull
  • docker run
docker build

Das Kommando docker build weist den Docker-Daemon an, ein Image zu erstellen (gepunktete Linie)

Soll das Image nicht selbst erstellt, sondern aus einem Repository im Docker-Hub geladen werden, kommt das Kommando docker pull zum Einsatz (gestrichelte Linie)

  • Wird der Docker-Daemon via docker run angewiesen, einen Container zu starten, prüft das Hintergrundprogramm zunächst, ob das entsprechende Container-Image lokal vorliegt
  • Ist dies der Fall, wird der Container ausgeführt (durchgezogene Linie)
  • Kann der Daemon das Image nicht finden, leitet dieser automatisch ein Pulling aus dem Repository ein

Betriebssysteme

Virtualisierung mit Linux

Docker auf die Virtualisierung mit Linux ausgerichtet

Container und Virtuelle Maschinen

Varianten
  • Hardware
  • Betriebssystem
    • Linux, FreeBSD, macOS, Windows, …
  • Virtualisierung

Herkömmliche Virtualisierung

Im rechten Bild wird eine herkömmliche Virtualisierung mit virtuellen Maschinen (VM) dargestellt

  • Dabei wird in der VM ein komplettes Betriebssystem (das "Gast-Betriebssystem") installiert und darin läuft dann die gewünschte Anwendung
  • Die Virtualisierung (VirtualBox, VMware, ...) läuft dabei als Anwendung auf dem Host-Betriebssystem und stellt dem Gast-Betriebssystem in der VM einen Rechner mit CPU, RAM, zur Verfügung und übersetzt die Systemaufrufe in der VM in die entsprechenden Aufrufe im Host-Betriebssystem
  • Dies benötigt in der Regel entsprechende Ressourcen: Durch das komplette Betriebssystem in der VM ist eine VM (die als Datei im Filesystem des Host-Betriebssystems liegt) oft mehrere 10GB groß
  • Für die Übersetzung werden zusätzlich Hardwareressourcen benötigt, d. h. hier gehen CPU-Zyklen und RAM "verloren"
  • Das Starten einer VM dauert entsprechend lange, da hier ein komplettes Betriebssystem hochgefahren werden muss
  • Dafür sind die Prozesse in einer VM relativ stark vom Host-Betriebssystem abgekapselt, so dass man hier von einer "Sandbox" sprechen kann: Viren o.ä
  • können nicht so leicht aus einer VM "ausbrechen" und auf das Host-Betriebssystem zugreifen (quasi nur über Lücken im Gast-Betriebssystem kombiniert mit Lücken in der Virtualisierungssoftware)

Virtualisierung auf Containerbasis

Im linken Bild ist eine schlanke Virtualisierung auf Containerbasis dargestellt

  • Die Anwendungen laufen direkt als Prozesse im Host-Betriebssystem, ein Gast-Betriebssystem ist nicht notwendig
  • Durch den geschickten Einsatz von namespaces und cgroups und anderen in Linux und FreeBSD verfügbaren Techniken werden die Prozesse abgeschottet, d. h. der im Container laufende Prozess "sieht" die anderen Prozesse des Hosts nicht
  • Die Erstellung und Steuerung der Container übernimmt hier beispielsweise Docker
  • Die Container sind dabei auch wieder Dateien im Host-Filesystem
  • Dadurch benötigen Container wesentlich weniger Platz als herkömmliche VMs, der Start einer Anwendung geht deutlich schneller und die Hardwareressourcen (CPU, RAM, ...) werden effizient genutzt
  • Nachteilig ist, dass hier in der Regel ein Linux-Host benötigt wird (für Windows wird mittlerweile der Linux-Layer (WSL) genutzt; für macOS wurde bisher eine Linux-VM im Hintergrund hochgefahren, mittlerweile wird aber eine eigene schlanke Virtualisierung eingesetzt)
  • Außerdem steht im Container üblicherweise kein graphisches Benutzerinterface zur Verfügung
  • Da die Prozesse direkt im Host-Betriebssystem laufen, stellen Container keine Sicherheitsschicht ("Sandboxen") dar!

In allen Fällen muss die Hardwarearchitektur beachtet werden: Auf einer Intel-Maschine können normalerweise keine VMs/Container basierend auf ARM-Architektur ausgeführt werden und umgekehrt

Anhang

Siehe auch

Kategorien
Unterseiten

Links

Weblinks

  1. https://docs.docker.com
  2. https://hub.docker.com/search
  3. https://de.wikipedia.org/wiki/Docker_(Software)
  4. https://www.hsbi.de/elearning/data/FH-Bielefeld/lm_data/lm_1359639/building/docker.html
  5. Offizielle Website
  6. Renaissance der Container-Virtualisierung mit Docker
  7. Einführung und Praxisbeispiele / Übersicht Docker und Container-Virtualisierung

</noinclude>

2 Grundlagen

Docker/Grundlagen

3 Installation

Docker/Installation - Docker auf Debian installieren

Beschreibung

Anforderungen

Docker/Engine läuft nativ unter Linux

Docker-Container sind leichtgewichtig

Im Vergleich zu virtuellen Maschinen

  • keine hohen Ansprüche an Hardware
Je komplexer die Anwendung ...
  • desto größer wird der Speicherbedarf des Containers und der Verbrauch weiterer Ressourcen
Systemvoraussetzungen
Anforderung Beschreibung
Prozessor (CPU) x86-64-Architektur, min. 2 GHz (Single-Core)
Arbeitsspeicher (RAM) min. 2 GB (für die Docker-Anwendung mit GUI benötigen Sie mindestens 4 GB RAM)
Betriebssystem Linux, Benutzer mit Root-Rechten
Kernel 4.19 oder höher, mit Unterstützung für cgroup, Namespaces, Overlay-Dateisystem und Seccomp-Filter
Festplattenspeicher min. 20 GB
Internetverbindung zum Downloaden von Docker-Images und Paketen

Installation

Installation aus dem Debian-Repository
sudo apt install docker.io docker-cli docker-compose docker-buildx

Docker ohne sudo

Um Docker-Befehle ohne sudo verwenden zu können, müssen Sie den Benutzer zur Docker-Gruppe hinzufügen.

sudo groupadd docker
sudo usermod -aG docker <USER>


4 Containerisieren

Skript/Linux/Docker

Beschreibung

Containerisieren einer Anwendung
  • Erstellung eines Dockerfiles zur Erstellung eines Images
  • Container starten
  • Laufende Anwendung prüfen
Beispiel

ToDo-Manager der auf Node.js basiert

  • JavaScript-Vorkenntnisse sind hier nicht erforderlich

Anwendung

Anwendung herunterladen

getting-started-app-Repositorys klonen

git clone https://github.com/docker/getting-started-app.git
Inhalt des geklonten Repositorys
tree -L 1 -a getting-started-app
└── getting-started-app/
    ├── .dockerignore
    ├── package.json
    ├── README.md
    ├── spec/
    ├── src/
    └── yarn.lock

Dockerfile

Dockerfile anlegen

Ein Dockerfile ist einfach eine textbasierte Datei, die ein Skript mit Anweisungen enthält

  • Docker verwendet dieses Skript, um ein Container-Image zu erstellen

Erstellen Sie im Verzeichnis getting-started-app eine Datei namens Dockerfile mit folgendem Inhalt

# syntax=docker/dockerfile:1

FROM node:lts-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000

Dieses Dockerfile beginnt mit einem node:lts-alpine-Basis-Image, einem leichtgewichtigen Linux-Image, auf dem Node.js und der Yarn-Paketmanager vorinstalliert sind

  • Es kopiert den gesamten Quellcode in das Image, installiert die notwendigen Abhängigkeiten und startet die Anwendung
Beschreibung
  1. syntax
  2. [1]
  3. [2]
  4. [3]
  5. [4]
  6. [5]
  7. [6]

Image

Image erstellen


cd getting-started-app
docker buildx build
docker buildx build -t getting-started .

Der Befehl docker buildx build verwendet das Dockerfile, um ein neues Image zu erstellen

  • Sie haben vielleicht bemerkt, dass Docker eine Menge "Schichten" heruntergeladen hat
  • Das liegt daran, dass Sie dem Builder mitgeteilt haben, dass Sie mit dem node:lts-alpine-Abbild beginnen wollen
  • Da Sie dieses aber nicht auf Ihrem Rechner hatten, musste Docker das Abbild herunterladen

Nachdem Docker das Image heruntergeladen hat, kopierten die Anweisungen aus der Dockerdatei Ihre Anwendung und installierten mithilfe von Garn die Abhängigkeiten Ihrer Anwendung

  • Die CMD-Direktive gibt den Standardbefehl an, der beim Starten eines Containers aus diesem Image ausgeführt werden soll

Das Flag -t schließlich kennzeichnet Ihr Image

  • Stellen Sie sich dies als einen für Menschen lesbaren Namen für das endgültige Image vor
  • Da Sie dem Abbild den Namen getting-started gegeben haben, können Sie auf dieses Abbild verweisen, wenn Sie einen Container starten

Das . am Ende des Docker-Build-Befehls teilt Docker mit, dass es im aktuellen Verzeichnis nach dem Dockerfile suchen soll

Container

Container starten

Starten Sie Ihren Container mit dem Befehl docker run und geben Sie den Namen des soeben erstellten Images an

docker run -d -p 3000:3000 getting-started

Mit dem Flag -d (kurz für --detach ) wird der Container im Hintergrund ausgeführt

  • Das bedeutet, dass Docker Ihren Container startet und Sie zur Terminal-Eingabeaufforderung zurückkehren
  • Außerdem werden keine Protokolle im Terminal angezeigt

Das Flag -p (kurz für --publish ) erstellt eine Port-Zuordnung zwischen dem Host und dem Container

  • Das Flag -p nimmt einen String-Wert im Format HOST:CONTAINER an, wobei HOST die Adresse des Hosts und CONTAINER der Port des Containers ist
  • Der Befehl leitet den Container-Port 3000/TCP auf den Host-Port 3000/TCP weiter.
  • Ohne die Port-Zuordnung wäre es nicht möglich, vom Host aus auf die Anwendung zuzugreifen.
  • Öffnen Sie nach ein paar Sekunden Ihren Webbrowser auf http://<host_ip>:3000
  • Sie sollten Ihre Anwendung sehen

Fügen Sie ein oder zwei Elemente hinzu und prüfen Sie, ob sie wie erwartet funktioniert

  • Sie können Elemente als vollständig markieren und entfernen
  • Ihr Frontend speichert erfolgreich Elemente im Backend

Zu diesem Zeitpunkt haben Sie einen laufenden ToDo-Listen-Manager mit ein paar Einträgen

Wenn Sie einen kurzen Blick auf Ihre Container werfen, sollten Sie mindestens einen Container sehen, der das Getting-Started-Image verwendet und auf Port 3000 läuft

  • Um Ihre Container zu sehen, können Sie die CLI oder die grafische Oberfläche von Docker Desktop verwenden
Container aufzulisten
docker ps

Es sollte eine ähnliche Ausgabe wie die folgende erscheinen

CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS        PORTS                      NAMES
df784548666d getting-started "docker-entrypoint.s..." vor 2 Minuten Up 2 Minuten 3000->3000/tcp priceless_mcclintock

Nächste Schritte

Docker/Aktualisieren

  • Änderung an Anwendungen vornehmen
  • Laufende Anwendung mit einem neuen Image aktualisieren
  • Weitere nützliche Befehle
Zurück

Grundlagen

Weiter

Aktualisieren



5 Aktualisieren

Docker/Aktualisieren

6 Datenbank

Skript/Linux/Docker

Datenbank

Persitente Datenbank

Persistieren der DB

  • Falls Sie es nicht bemerkt haben, ist Ihre ToDo-Liste jedes Mal leer, wenn Sie den Container starten. Warum ist das so? In diesem Teil werden wir uns ansehen, wie der Container funktioniert

Das Dateisystem des Containers

  • Wenn ein Container läuft, verwendet er die verschiedenen Schichten eines Images für sein Dateisystem.
  • Jeder Container erhält auch seinen eigenen "Scratch Space", um Dateien zu erstellen/zu aktualisieren/zu löschen.
  • Alle Änderungen werden in einem anderen Container nicht sichtbar, selbst wenn sie das gleiche Image verwenden

Sehen Sie dies in der Praxis

Um dies in Aktion zu sehen, werden Sie zwei Container starten. In einem Container erstellen Sie eine Datei. In dem anderen Container überprüfen Sie, ob die gleiche Datei existiert.

1. Starten Sie einen Alpine-Container und erstellen Sie in diesem eine neue Datei

docker run --rm alpine touch greeting.txt

2. Alle Befehle, die Sie nach dem Image-Namen (in diesem Fall Alpine) angeben, werden innerhalb des Containers ausgeführt. In diesem Fall legt der Befehl touch greeting.txt eine Datei namens greeting.txt im Dateisystem des Containers an. 3. Starten Sie einen neuen Alpine-Container und verwenden Sie den Befehl stat, um zu überprüfen, ob die Datei existiert

docker run --rm alpine stat greeting.txt

Sie sollten eine ähnliche Ausgabe wie die folgende sehen, die anzeigt, dass die Datei im neuen Container nicht existiert.

stat: can't stat 'greeting.txt': No such file or directory

Die Datei greeting.txt, die vom ersten Container erstellt wurde, existiert nicht im zweiten Container.

  • Das liegt daran, dass die beschreibbare "oberste Schicht" eines jeden Containers isoliert ist.
  • Auch wenn beide Container dieselben Schichten verwenden, die das Basis-Image bilden, ist die beschreibbare Schicht für jeden Container einzigartig
Hinweis
Der Parameter --rm des Befehls docker run wird verwendet, um den Container und seine beschreibbare Ebene nach Abschluss des Prozesses automatisch zu löschen.

Container-Volumen

  • Jeder Container wird beim Start erneut auf Basis des Images erstellt
  • Ein Container kann während der Laufzeit Dateien erstellen, ändern und löschen. Allerdings gehen alle Änderungen beim Entfernen des Containers verloren
  • Durch die Verwendung von Volumes können Daten außerhalb des Containers gespeichert und beim Entfernen des Containers beibehalten werden
Volumes
  • Bieten die Möglichkeit, bestimmte Dateisystempfade des Containers wieder mit dem Host-Rechner zu verbinden.
  • Wenn Sie ein Verzeichnis im Container mounten, werden Änderungen an diesem Verzeichnis auch auf dem Host-Rechner sichtbar.
  • Wenn Sie dasselbe Verzeichnis über mehrere Container-Neustarts hinweg mounten, sehen Sie dieselben Dateien

Es gibt zwei Haupttypen von Volumes. Letztendlich werden beide verwendet, jedoch wird zunächst mit Volume Mounts begonnen.

Persistieren der ToDo-Daten

  • Standardmäßig speichert die Todo-App ihre Daten in einer SQLite-Datenbank unter /etc/todos/todo.db im Dateisystem des Containers
  • SQLite ist eine relationale Datenbank, die alle Daten in einer einzigen Datei ablegt
  • Da die Datenbank aus einer einzelnen Datei besteht, kann diese Datei auf dem Host-System persistiert und von einem neuen Container weiterverwendet werden, um den vorherigen Zustand beizubehalten
  • Durch das Erstellen eines Volumes und das Mounten an das Verzeichnis, in dem die Daten liegen, werden die Daten dauerhaft gespeichert
  • Alle Schreibvorgänge in die Datei todo.db werden auf dem Host im Volume gespeichert
  • Docker verwaltet das Volume vollständig, einschließlich des physischen Speicherorts. Es genügt, den Namen des Volumes zu kennen

Erstellen eines Volumes und Starten des Containers

Sie können das Volume erstellen und den Container über die CLI oder die grafische Oberfläche von Docker Desktop starten.

1. Erstellen Sie ein Volume mit dem Befehl docker volume create

docker volume create todo-db

2. Stoppen und entfernen Sie den todo app Container erneut mit docker rm -f <id>, da er noch läuft, ohne das persistente Volume zu verwenden

3. Starten Sie den todo-App-Container, aber fügen Sie die Option --mount hinzu, um ein Volume zu mounten. Geben Sie dem Volume einen Namen und mounten Sie es in /etc/todos im Container, wodurch alle Dateien, die unter dem Pfad erstellt werden, erfasst werden

docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
Hinweis
Wenn Sie Git Bash verwenden, müssen Sie für diesen Befehl eine andere Syntax verwenden.
docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=//etc/todos getting-started

Überprüfen, ob die Daten erhalten bleiben

1. Sobald der Container hochgefahren ist, öffnen Sie die Anwendung und fügen Sie Ihrer ToDo-Liste einige Einträge hinzu

2. Stoppen und entfernen Sie den Container für die Todo-App. Verwenden Sie Docker Desktop oder docker ps, um die ID zu ermitteln, und dann docker rm -f <id>, um ihn zu entfernen.

3. Starten Sie einen neuen Container unter Verwendung der vorherigen Schritte

4. Öffnen Sie die App. Sie sollten Ihre Objekte immer noch in Ihrer Liste sehen

5. Entfernen Sie den Container, wenn Sie mit dem Auschecken Ihrer Liste fertig sind

Sie haben nun gelernt, wie man Daten persistiert

Tauchen Sie in das Volumen ein

Um herauszufinden, wo Docker die Dateien eines bestimmten Volumes speichert, kann man den Befehl docker volume inspect verwenden.

docker volume inspect todo-db

Sie sollten eine Ausgabe wie die folgende sehen:

[

{

"CreatedAt": "2019-09-26T02:18:36Z",

"Driver": "local",

"Labels": {},

"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",

"Name": "todo-db",

"Optionen": {},

"Scope": "local"

}

]

Der Mountpoint ist der tatsächliche Speicherort der Daten auf der Festplatte.

Hinweis

Beachten Sie, dass Sie auf den meisten Rechnern über Root-Zugriff verfügen müssen, um vom Host aus auf dieses Verzeichnis zuzugreifen

Zusammenfassung

In diesem Abschnitt haben Sie gelernt, wie man Containerdaten persistiert

Nächste Schritte

Als Nächstes erfahren Sie, wie Sie Ihre Anwendung mithilfe von Bind Mounts effizienter entwickeln können


Zurück

Aktualisieren

Weiter

Mounts


Anhang

Siehe auch



Dokumentation

Links

Projekt

Weblinks

7 Mounts

Skript/Linux/Docker

Beschreibung

  • Datenbank persistieren
  • Änderungen an Anwendungen während der Entwicklung sehen, ohne das Image neu zu erstellenIm nächsten Abschnitt
  • Volume-Mounts und Bind-Mounts unterstützt Docker auch andere Mount-Typen und Speichertreiber
    • um komplexere und spezialisierte Anwendungsfälle zu behandeln

Mounts

Bind Mounts

Methode in Docker, bei der ein Verzeichnis oder eine Datei vom Hostsystem in einen Container eingebunden wird

  • Dabei verwendet der Container die echten Daten vom Host, und Änderungen im Container wirken sich unmittelbar auf den Host aus (und umgekehrt)
Verwenden von Bind Mounts

Im vorherigen Abschnitt haben Sie ein Volume Mount verwendet, um die Daten in Ihrer Datenbank zu speichern Bind Mounts werden ebenfalls verwendet und weisen einige Besonderheiten auf:

  • Ein Bind Mount verbindet ein echtes Verzeichnis oder eine Datei vom Host-System direkt mit einem Container
  • Im Gegensatz zu einem Volume Mount werden die Daten physisch auf dem Host an dem angegebenen Pfad gespeichert und nicht im von Docker verwalteten Speicher
  • Änderungen, die im Container vorgenommen werden, sind sofort auf dem Host sichtbar – und umgekehrt
  • Diese Methode eignet sich besonders für Entwicklung und Debugging, wenn es wichtig ist, Codeänderungen sofort zu sehen, ohne das Image neu zu bauen
  • Bind Mount hängt von der Dateistruktur und den Pfaden des Hostsystems ab, was die Portabilität der Container verringert

Im Folgenden wird die Verwendung von Bind Mounts und des Tools nodemon beschrieben, um Dateiänderungen zu überwachen und die Anwendung automatisch neu zu starten

Vergleiche von Volume-Typen

Beispiele
Benanntes Volume type=volume,src=my-volume,target=/usr/local/data
Bind-Mount type=bind,src=/path/to/data,target=/usr/local/data
Unterschiede Volume-Einhängungen und Bind-Einhängungen
Benannte Volumes Bind-Mounts
Speicherort des Hosts Docker wählt aus Sie entscheiden
Füllt das neue Volume mit Containerinhalten Ja Nein
Unterstützt Volume-Treiber Ja Nein

Bind-Mounts

Um mit Bind Mounts zu arbeiten, kann ein kurzes Experiment durchgeführt werden, um das Funktionsprinzip praktisch zu verstehen

1. In das Verzeichnis getting-started-app wechseln

2. Den folgenden Befehl ausführen, um Bash in einem Ubuntu-Container mit einem Bind Mount zu starten

docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash
  • Die Option --mount type=bind weist Docker an, einen Bind-Mount zu erstellen, wobei src das aktuelle Arbeitsverzeichnis auf dem Host-Rechner (getting-started-app) und target das Verzeichnis ist, das im Container erscheinen soll (/src)

3. Nach dem Ausführen des Befehls startet Docker eine interaktive Bash-Sitzung im Stammverzeichnis des Dateisystems des Containers

pwd; ls
 bin dev home media opt root sbin srv tmp var boot etc lib mnt proc run src sys usr

4. Wechseln Sie in das src-Verzeichnis

  • Dies ist das Verzeichnis, das Sie beim Start des Containers gemountet haben
  • Wenn Sie den Inhalt dieses Verzeichnisses auflisten, werden die gleichen Dateien angezeigt wie im Verzeichnis getting-started-app auf Ihrem Host-Rechner
cd src; ls
 Dockerfile node_modules package.json spec src yarn.lock

5. Erstellen Sie eine neue Datei namens myfile.txt

touch myfile.txt; ls
Dockerfile myfile.txt node_modules package.json spec src yarn.lock

6. Öffnen Sie das Verzeichnis getting-started-app auf dem Host und stellen Sie fest, dass sich die Datei myfile.txt in diesem Verzeichnis befindet

├── getting-started-app/
│ ├── Dockerdatei
│ ├── meineDatei.txt
│ ├── node_modules/
│ ├── package.json
│ ├── spec/
│ ├── src/
│ └── yarn.lock
  • Löschen Sie auf dem Host die Datei myfile.txt
  • Listen Sie im Container noch einmal den Inhalt des app-Verzeichnisses auf
  • Stellen Sie fest, dass die Datei jetzt verschwunden ist
ls
Dockerfile node_modules package.json spec src yarn.lock

7. Beenden Sie die interaktive Containersitzung mit Strg + D

Entwicklungscontainer

  • Die Verwendung von Bind-Mounts ist für lokale Entwicklungsumgebungen üblich
  • Der Vorteil ist, dass auf dem Entwicklungsrechner nicht alle Build-Tools und Umgebungen installiert sein müssen
  • Mit einem einzigen Docker-Run-Befehl ruft Docker die Abhängigkeiten und Tools ab

Ausführen Anwendung

Ausführen Anwendung in einem Entwicklungscontainer

Die folgenden Schritte beschreiben, wie man einen Entwicklungscontainer mit einem Bind-Mount ausführt, der die folgenden Aufgaben erfüllt

  • Binden Sie Ihren Quellcode in den Container ein
  • Installieren aller Abhängigkeiten
  • Starten von nodemon, um auf Änderungen im Dateisystem zu achten
  • Vergewissern Sie sich, dass derzeit keine Getting-Started-Container laufen

1. Führen Sie den folgenden Befehl aus dem get-started-app-Verzeichnis aus

docker run -dp 3000:3000 \
-w /app --mount type=bind,src="$(pwd)",target=/app \
node:18-alpine \
sh -c "yarn install && yarn run dev"
Zeile Parameter Beschreibung
1 -dp 3000:3000 Wird im abgetrennten Modus (im Hintergrund) ausgeführt und erstellt eine Port-Zuordnung
2 -w /app Legt das "Arbeitsverzeichnis" oder das aktuelle Verzeichnis fest, von dem aus der Befehl ausgeführt werden soll
3 --mount type=bind,src="$(pwd)",target=/app Bindet das aktuelle Verzeichnis vom Host in das /app-Verzeichnis im Container ein
4 node:18-alpine Das zu verwendende Image
  • Beachten Sie, dass dies das Basis-Image für Ihre App aus dem Dockerfile ist
5 sh -c "yarn install && yarn run dev" Der Befehl
  • Sie starten eine Shell mit sh (Alpine hat keine Bash) und führen yarn install aus, um Pakete zu installieren, und führen dann yarn run dev aus, um den Entwicklungsserver zu starten
  • Wenn Sie in der package.json nachsehen, werden Sie sehen, dass das dev-Skript nodemon startet

2. Sie können die Protokolle mit docker logs -f <container-id> einsehen

  • Sie wissen, dass Sie bereit sind, wenn Sie dies sehen:
$ docker logs -f <container-id>
nodemon -L src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000

3. Wenn Sie mit dem Betrachten der Protokolle fertig sind, beenden Sie diese mit Strg+ C

Entwickeln von Anwendungen

Aktualisieren Sie Ihre Anwendung auf Ihrem Host-Rechner und sehen Sie sich die Änderungen im Container an
  • Ändern Sie in der Datei src/static/js/app.js in Zeile 109 die Schaltfläche "Element hinzufügen" so, dass sie einfach "Hinzufügen" lautet:
- {submitting ? 'Adding...' : 'Add Item'}
+ {submitting ? 'Adding...' : 'Add'}
  • Speichern Sie die Datei
  • Aktualisieren Sie die Seite in Ihrem Webbrowser, und Sie sollten sehen, dass die Änderung aufgrund des Bind-Mounts fast sofort übernommen wird
  • Nodemon erkennt die Änderung und startet den Server neu
  • Es kann ein paar Sekunden dauern, bis der Node-Server neu gestartet ist
  • Wenn Sie eine Fehlermeldung erhalten, versuchen Sie, die Seite nach ein paar Sekunden neu zu starten
  • Sie können alle anderen Änderungen vornehmen, die Sie vornehmen möchten
  • Jedes Mal, wenn Sie eine Änderung vornehmen und eine Datei speichern, wird die Änderung aufgrund des Bind-Mounts in den Container übernommen
  • Wenn Nodemon eine Änderung feststellt, startet es die Anwendung innerhalb des Containers automatisch neu

Wenn Sie fertig sind, stoppen Sie den Container und erstellen Sie Ihr neues Image mit:

docker buildx build -t getting-started .

Nächste Schritte

Zur Vorbereitung der Anwendung auf den Produktionseinsatz sollte die Datenbank von SQLite auf ein skalierbareres System migriert werden.

  • Für eine einfache Umsetzung wird weiterhin eine relationale Datenbank verwendet, wobei die Anwendung auf MySQL umgestellt wird.
  • Im nächsten Abschnitt wird beschrieben, wie MySQL ausgeführt und die Kommunikation zwischen Containern ermöglicht wird.

Anhang

Siehe auch



Dokumentation

Links

Projekt

Weblinks

</noinclude>

8 Multi-Container

Docker/Multi-Container - Multi-Container

Beschreibung

Mehrcontainer-Anwendungen

Die Mehrcontainer-Architektur trennt Zuständigkeiten, vereinfacht den Betrieb und ermöglicht gezieltes Skalieren

  • Datenbankkomponenten (z. B. MySQL) werden als separater Container ausgeführt
Entwurfsprinzip

Ein Container = eine klar abgegrenzte Aufgabe

Anwendungsteile bleiben lose gekoppelt, Images bleiben kompakt und wartbar

Vorteile
  • API/Frontend und Datenbank haben unterschiedliche Lastprofile und werden unabhängig skaliert
  • Anwendungs- und DB-Images werden getrennt gebaut, getestet und aktualisiert
  • Lokal kann die Datenbank in einem Container laufen; in der Produktion kann dasselbe System einen verwalteten Datenbankdienst nutzen – ohne Änderungen am Anwendungs-Image
  • Pro Container ein Hauptprozess
  • Mehrere Prozesse erfordern einen Prozessmanager und erhöhen die Komplexität von Start/Shutdown
Empfehlung
  • MySQL separat betreiben und die Anwendung als Verbund miteinander gekoppelter Container ausführen
  • So bleibt die Architektur verständlich, betrieblich robust und leicht anpassbar (Skalierung, Updates, Umgebungswechsel)

Jetzt haben Sie eine Anwendung, die ihre Daten in einer externen Datenbank speichert, die in einem separaten Container läuft

  • Sie haben ein wenig über Container-Netzwerke und die Erkennung von Diensten mithilfe von DNS gelernt

Container-Vernetzung

Docker: gemeinsames Containernetzwerk
  • Standardmäßig sind Container isoliert und sehen weder Prozesse noch andere Container auf demselben Host
  • Damit Container Daten austauschen können, benötigen sie ein gemeinsames Netzwerk
  • Dazu müssen die Container in dasselbe Netzwerk eingebunden werden

MySQL starten

Es gibt zwei Möglichkeiten, einen Container in ein Netzwerk einzubinden

  • Netzwerk beim Start des Containers zuweisen
  • Bereits laufenden Container mit einem Netzwerk verbinden

In diesem Abschnitt wird zuerst ein Netzwerk erstellt und der MySQL-Container beim Start daran angeschlossen

  • Erstellen Sie das Netzwerk
docker network create todo-app
  • MySQL-Container starten und mit dem Netzwerk verbinden
  • Dabei werden Umgebungsvariablen gesetzt, die MySQL für die Initialisierung verwendet
docker run -d \
 --network todo-app --network-alias mysql \
 -v todo-mysql-data:/var/lib/mysql \
 -e MYSQL_ROOT_PASSWORD=secret \
 -e MYSQL_DATABASE=todos \
 mysql:8.0

Im vorherigen Befehl sehen Sie die --network-alias-Flagge

  • In einem späteren Abschnitt werden Sie mehr über dieses Flag erfahren.(!)
Hinweis
Der obige Befehl gibt das Volume todo-mysql-data an, das in /var/lib/mysql gemountet ist
  • Docker erstellt das Volume automatisch, falls es zuvor nicht mit docker volume create erstellt wurde
Überprüfung der Verbindung zur Datenbank
docker exec -it <mysql-container-id> mysql -u root -p
Wenn die Passwortabfrage erscheint, geben Sie secret ein
  • Führen Sie in der MySQL-Shell eine Liste der Datenbanken auf und überprüfen Sie, ob die Datenbank todos angezeigt wird
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| todos |
+--------------------+
5 rows in set (0.00 sec)
  • Beenden Sie die MySQL-Shell, um zur Shell auf Ihrem Rechner zurückzukehren
mysql> exit

Sie haben jetzt eine todos-Datenbank und können sie benutzen

Verbindung zu MySQL herstellen

Nach dem Start des MySQL-Containers kann innerhalb desselben Docker-Netzwerks über DNS auf den Dienst zugegriffen werden (Hostname: mysql)

  • Zur Überprüfung der Namensauflösung wird der Diagnose-Container nicolaka/netshoot verwendet
  • Netshoot-Container im selben Netzwerk starten
docker run -it --network todo-app nicolaka/netshoot
  • Im Container DNS-Auflösung für den Hostnamen mysql testen
dig mysql

Das Ergebnis sollte in etwa wie folgt aussehen:

; <<>> DiG 9.18.8 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mysql.				IN	A

;; ANSWER SECTION:
mysql.			600	IN	A	172.23.0.2

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Tue Oct 01 23:47:24 UTC 2019
;; MSG SIZE rcvd: 44
  • Im ANSWER SECTION erscheint ein A-Record für mysql, der auf 172.23.0.2 zeigt (die tatsächliche IP kann abweichen)
  • Die Auflösung erfolgt über den Docker-internen DNS-Resolver, weil dem MySQL-Container zuvor der Netzwerkalias --network-alias mysql zugewiesen wurde
  • Docker-DNS läuft typischerweise unter 127.0.0.11 und löst Service-/Aliasnamen netzwerkintern
  • mysql ist außerhalb des Docker-Netzwerks kein gültiger FQDN, innerhalb des Netzwerks jedoch als Alias nutzbar

Anwendungen im selben Docker-Netzwerk verbinden sich daher einfach mit dem Hostnamen mysql


Starten Sie Ihre Anwendung mit MySQL

Die todo-App unterstützt das Setzen einiger Umgebungsvariablen, um die MySQL-Verbindungseinstellungen festzulegen

  • Diese sind
Parameter Beschreibung
MYSQL_HOST der Hostname für den laufenden MySQL-Server
MYSQL_USER der Benutzername, der für die Verbindung verwendet werden soll
MYSQL_PASSWORD das Passwort, das für die Verbindung verwendet werden soll
MYSQL_DB die zu verwendende Datenbank nach der Verbindung
Sicherheitshinweis
  • Während die Verwendung von env vars zur Festlegung von Verbindungseinstellungen für die Entwicklung allgemein akzeptiert wird, wird davon dringend abgeraten, wenn Anwendungen in Produktion laufen
  • Ein sicherer Mechanismus besteht darin, die Unterstützung für Geheimnisse des Orchestrators zu nutzen (Docker Swarm Secrets, Kubernetes Secrets)
  • In Laufzeit-Containern werden Geheimnisse i. d. R. als Dateien bereitgestellt
  • Viele Images/Apps (u. a. MySQL und die Todo-App) unterstützen dazu Umgebungsvariablen mit dem Suffix _FILE, die auf eine Datei mit dem Wert verweisen
  • Docker wertet _FILE nicht aus; die Anwendung muss die Variable lesen und den Dateiinhalt verwenden
  • Für MySQL: MYSQL_PASSWORD_FILE statt MYSQL_PASSWORD
Erstellen eines MYSQL-Containers
  • Geben Sie jede der vorherigen Umgebungsvariablen an und verbinden Sie den Container mit Ihrem App-Netzwerk
  • Stellen Sie sicher, dass Sie sich im Verzeichnis getting-started-app befinden, wenn Sie diesen Befehl ausführen
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:18-alpine \
sh -c "yarn install && yarn run dev"
  • Wenn Sie sich die Logs für den Container ansehen (docker logs -f <container-id>), sollten Sie eine Meldung ähnlich der folgenden sehen, die anzeigt, dass die mysql-Datenbank verwendet wird
nodemon src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Connected to mysql db at host mysql
Listening on port 3000
  • Öffnen Sie die Anwendung in Ihrem Browser und fügen Sie Ihrer ToDo-Liste ein paar Einträge hinzu
  • Verbinden Sie sich mit der mysql-Datenbank und prüfen Sie, ob die Einträge in die Datenbank geschrieben werden
  • Denken Sie daran, dass das Passwort geheim ist
docker exec -it <mysql-container-id> mysql -p todos

Und in der mysql-Shell führen Sie Folgendes aus:

mysql> select * from todo_items;

+--------------------------------------+--------------------+-----------+

| id | name | completed |

+--------------------------------------+--------------------+-----------+

| c906ff08-60e6-44e6-8f49-ed56a0853e85 | Tue erstaunliche Dinge! | 0 |

| 2912a79e-8486-4bc3-a4c5-460793a575ab | Sei fantastisch! | 0 |

+--------------------------------------+--------------------+-----------+

Deine Tabelle sieht anders aus, weil sie deine Artikel enthält

  • Aber Sie sollten sie dort gespeichert sehen

Aufruf

Optionen

Unix GNU Parameter Beschreibung

Parameter

Umgebungsvariablen

Exit-Status

Wert Beschreibung
0 Erfolg
>0 Fehler

Anwendung

Problembehebung

Konfiguration

Dateien

Datei Beschreibung


9 Compose

Docker/Compose - Verwaltung mehrerer Container, die gemeinsam eine Anwendung bilden

Beschreibung

Docker Compose ist ein Werkzeug zur Definition und Verwaltung mehrerer Container, die gemeinsam eine Anwendung bilden.

Die gesamte Umgebung wird in einer compose.yaml-Datei beschrieben und kann mit einem einzigen Befehl gestartet oder gestoppt werden.

Der Vorteil von Compose besteht darin, dass Sie Ihren Anwendungsstack in einer Datei definieren können, diese im Stammverzeichnis Ihres Projekt-Repositorys aufbewahren können (es ist jetzt versionskontrolliert) und es anderen Personen leicht ermöglichen, zu Ihrem Projekt beizutragen.

  • Jemand müsste nur Ihr Repository klonen und die Anwendung mit Compose starten.
  • Tatsächlich gibt es auf GitHub/GitLab eine ganze Reihe von Projekten, die genau das tun
Vorteile
  • Deklarative, versionskontrollierbare Konfiguration in compose.yaml.
  • Start, Stopp und Bereinigung des gesamten Stacks mit einem Befehl.
  • Isolierung und Service-Discovery über benannte Netzwerke und Volumes.
  • Skalierung und gemeinsame Log-Sicht pro Dienst.

In diesem Abschnitt wird Docker Compose vorgestellt

  • Definition und Freigabe von Multi-Service-Anwendungen

Erstellen Sie die Compose-Datei

Erstellen Sie im Verzeichnis getting-started-app eine Datei namens compose.yaml

├── getting-started-app/
│ ├── Dockerdatei
│ ├── compose.yaml
│ ├── node_modules/
│ ├── package.json
│ ├── spec/
│ ├── src/
│ └── yarn.lock

Definieren Sie den Anwendungsdienst

In Teil 6 haben Sie den folgenden Befehl verwendet, um den Anwendungsdienst zu starten

docker run -dp 3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:lts-alpine \
  sh -c "yarn install && yarn run dev"

In YAML sieht diese Konfiguration wie folgt aus:

services:
  app:
    image: node:lts-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

Definieren Sie den MySQL-Dienst

Nun ist es an der Zeit, den MySQL-Dienst zu definieren.

  • Der Befehl, den Sie für diesen Container verwendet haben, war der folgende:
docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:8.0

Zu diesem Zeitpunkt sollte Ihre komplette compose.yaml wie folgt aussehen:

services:
  app:
    image: node:lts-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

Vollständige Übersicht über die Parameter

Die folgende Tabelle zeigt die Entsprechung zwischen den Parametern des Befehls docker run und den jeweiligen YAML-Direktiven in einer compose.yaml-Datei.

  • Dadurch lässt sich nachvollziehen, wie Docker Compose dieselben Einstellungen automatisch umsetzt.
YAML docker run-Parameter Beschreibung
Dienst: app
image: node:lts-alpine node:lts-alpine Basis-Image.
command: sh -c "yarn install && yarn run dev" sh -c "yarn install && yarn run dev" Startkommando (überschreibt CMD).
ports:
  3000:3000
-p 3000:3000 Port-Mapping Host->Container.
working_dir: /app -w /app Arbeitsverzeichnis im Container.
volumes:
  ./:/app
-v "$(pwd):/app" Bind-Mount des Projektverzeichnisses.
environment: MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB -e MYSQL_HOST=mysql
-e MYSQL_USER=root
-e MYSQL_PASSWORD=secret
-e MYSQL_DB=todos
Umgebungsvariablen für die App.
Dienst: mysql
image: mysql:8.0 mysql:8.0 MySQL-Server-Image.
volumes:
  todo-mysql-data:/var/lib/mysql
-v todo-mysql-data:/var/lib/mysql Benanntes Volume für persistente Daten.
environment: MYSQL_ROOT_PASSWORD, MYSQL_DATABASE -e MYSQL_ROOT_PASSWORD=secret
-e MYSQL_DATABASE=todos
Initiale Datenbankparameter.
Servicename: mysql --network-alias mysql DNS-Name im Container-Netzwerk (automatisch durch Servicenamen).
Top-Level
volumes:
  todo-mysql-data:
Definition des benannten Volumes.

Starten Sie den Anwendungsstack

Nun, da Sie Ihre compose.yaml-Datei haben, können Sie Ihre Anwendung starten.

  • Vergewissern Sie sich zunächst, dass keine anderen Kopien der Container ausgeführt werden.
  • Verwenden Sie docker ps, um die Container aufzulisten und docker rm -f <ids>, um sie zu entfernen
  • Starten Sie den Anwendungsstapel mit dem Befehl docker compose up.
  • Fügen Sie das Flag -d hinzu, um alles im Hintergrund laufen zu lassen
docker compose up -d
  • Wenn Sie den vorherigen Befehl ausführen, sollten Sie eine Ausgabe wie die folgende sehen
✔ Network getting-started-app_default         Created                                                                                                                                                        0.1s
✔ Volume getting-started-app_todo-mysql-data  Created                                                                                                                                                        0.0s
✔ Container getting-started-app-mysql-1       Started                                                                                                                                                        0.3s
✔ Container getting-started-app-app-1         Started

Sie werden feststellen, dass Docker Compose sowohl das Volume als auch ein Netzwerk erstellt hat.

  • Standardmäßig erstellt Docker Compose automatisch ein Netzwerk speziell für den Anwendungsstapel (deshalb haben Sie kein Netzwerk in der Compose-Datei definiert).
  • Sehen Sie sich die Protokolle mit dem Befehl docker compose logs -f an.
  • Sie werden sehen, dass die Protokolle der einzelnen Dienste in einen einzigen Stream verschachtelt sind.
  • Dies ist sehr nützlich, wenn Sie auf zeitliche Probleme achten wollen.
  • Die Markierung -f folgt dem Protokoll, so dass Sie eine Live-Ausgabe erhalten, während es erzeugt wird

Wenn Sie den Befehl bereits ausgeführt haben, werden Sie eine Ausgabe sehen, die wie folgt aussieht:

mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
mysql_1  | Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
app_1    | Connected to mysql db at host mysql
app_1    | Listening on port 3000
  • Der Name des Dienstes wird am Anfang der Zeile angezeigt (oft farbig), um die Unterscheidung der Meldungen zu erleichtern.
  • Wenn Sie die Protokolle für einen bestimmten Dienst anzeigen möchten, können Sie den Namen des Dienstes an das Ende des Befehls logs anhängen (z. B. docker compose logs -f app).
  • Zu diesem Zeitpunkt sollten Sie in der Lage sein, Ihre App in Ihrem Browser auf http://<server_ip>:3000/ zu öffnen und zu sehen, dass sie läuft

Sehen Sie den App-Stack im Docker Desktop Dashboard

Im Docker Desktop Dashboard sehen Sie, dass es eine Gruppe namens getting-started-app gibt.

  • Dies ist der Projektname von Docker Compose und wird verwendet, um die Container zusammenzufassen.
  • Standardmäßig ist der Projektname einfach der Name des Verzeichnisses, in dem sich die compose.yaml befand

Wenn Sie den Stack erweitern, sehen Sie die beiden Container, die Sie in der Compose-Datei definiert haben.

  • Die Namen sind auch etwas aussagekräftiger, da sie dem Muster <Service-Name>-<Replikat-Nummer> folgen.
  • So ist es sehr einfach, schnell zu erkennen, welcher Container Ihre Anwendung und welcher Container die mysql-Datenbank ist

Alles abreißen

Wenn Sie bereit sind, alles abzubauen, führen Sie einfach docker compose down aus oder drücken Sie den Mülleimer im Docker Desktop Dashboard für die gesamte Anwendung.

  • Die Container werden gestoppt und das Netzwerk wird entfernt
Warnung

Standardmäßig werden benannte Volumes in Ihrer Compose-Datei nicht entfernt, wenn Sie docker compose down ausführen.

  • Wenn Sie die Volumes entfernen möchten, müssen Sie das Flag --volumes hinzufügen

Das Docker Desktop Dashboard entfernt die Volumes nicht, wenn Sie den Anwendungsstapel löschen

Nächste Schritte

Image Erstellung

Anhang

Siehe auch



Dokumentation

Links

Projekt

Weblinks

  1. Compose-Übersicht
  2. Compose-Dateireferenz
  3. Compose CLI-Referenz

10 Image-Erstellung

Docker/Image-Erstellung

11 Ausblick

Docker/Ausblick