Skript/Linux/Docker: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
K Textersetzung - „Docker/Workshop/“ durch „Docker/“ |
||
| Zeile 5: | Zeile 5: | ||
| 1 || [[Docker/Workshop|Überblick]] | | 1 || [[Docker/Workshop|Überblick]] | ||
|- | |- | ||
| 2 || [[Docker | | 2 || [[Docker/Grundlagen]] | ||
|- | |- | ||
| 3 || [[Docker/Installation|Installation]] | | 3 || [[Docker/Installation|Installation]] | ||
|- | |- | ||
| 4 || [[Docker | | 4 || [[Docker/Containerisieren|Containerisieren]] | ||
|- | |- | ||
| 5 || [[Docker | | 5 || [[Docker/Aktualisieren|Aktualisieren]] | ||
|- | |- | ||
| 6 || [[Docker | | 6 || [[Docker/Datenbank|Datenbank]] | ||
|- | |- | ||
| 7 || [[Docker | | 7 || [[Docker/Mounts|Mounts]] | ||
|- | |- | ||
| 8 || [[Docker | | 8 || [[Docker/Multi-Container|Multi-Container]] | ||
|- | |- | ||
| 9 || [[Docker | | 9 || [[Docker/Compose|Compose]] | ||
|- | |- | ||
| 10 || [[Docker | | 10 || [[Docker/Image-Erstellung|Image-Erstellung]] | ||
|- | |- | ||
| 11 || [[Docker | | 11 || [[Docker/Ausblick|Ausblick]] | ||
|} | |} | ||
| Zeile 30: | Zeile 30: | ||
= 2 Grundlagen = | = 2 Grundlagen = | ||
{{:Docker | {{:Docker/Grundlagen}} | ||
= 3 Installation = | = 3 Installation = | ||
| Zeile 36: | Zeile 36: | ||
= 4 Containerisieren = | = 4 Containerisieren = | ||
{{:Docker | {{:Docker/Containerisieren}} | ||
= 5 Aktualisieren = | = 5 Aktualisieren = | ||
{{:Docker | {{:Docker/Aktualisieren}} | ||
= 6 Datenbank = | = 6 Datenbank = | ||
{{:Docker | {{:Docker/Datenbank}} | ||
= 7 Mounts = | = 7 Mounts = | ||
{{:Docker | {{:Docker/Mounts}} | ||
= 8 Multi-Container = | = 8 Multi-Container = | ||
{{:Docker | {{:Docker/Multi-Container}} | ||
= 9 Compose = | = 9 Compose = | ||
{{:Docker | {{:Docker/Compose}} | ||
= 10 Image-Erstellung = | = 10 Image-Erstellung = | ||
{{:Docker | {{:Docker/Image-Erstellung}} | ||
= 11 Ausblick = | = 11 Ausblick = | ||
{{:Docker | {{:Docker/Ausblick}} | ||
[[Kategorie:Skript/Linux]] | [[Kategorie:Skript/Linux]] | ||
Version vom 2. November 2025, 11:44 Uhr
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
2 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
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
-pnimmt 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
- Änderung an Anwendungen vornehmen
- Laufende Anwendung mit einem neuen Image aktualisieren
- Weitere nützliche Befehle
- Zurück
- Weiter
5 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
--rmdes Befehlsdocker runwird 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
- Weiter
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=bindweist Docker an, einen Bind-Mount zu erstellen, wobeisrcdas aktuelle Arbeitsverzeichnis auf dem Host-Rechner (getting-started-app) undtargetdas 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
|
| 5 | sh -c "yarn install && yarn run dev" | Der Befehl
|
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
- https://docs.docker.com/get-started/workshop/06_bind_mounts
- Docker CLI-Referenz
- Verwalten von Daten in Docker
</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

- 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
Anhang
Siehe auch