Skript/Docker: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| (41 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
<noinclude> | |||
'''Skript/Docker''' - [[Docker]] verstehen und anwenden | |||
=== Inhalt === | |||
{{:Skript/Docker/Inhalt}} | |||
= 01 Überblick = | |||
{{:Docker}} | |||
= | = 02 Grundlagen = | ||
{{:Docker/Grundlagen}} | {{:Docker/Grundlagen}} | ||
= | = 03 Installation = | ||
{{:Docker/Installation}} | {{:Docker/Installation}} | ||
= | = 04 Containerisieren = | ||
{{:Docker/Containerisieren}} | {{:Docker/Containerisieren}} | ||
= | = 05 Aktualisieren = | ||
{{:Docker/Aktualisieren}} | {{:Docker/Aktualisieren}} | ||
= | = 06 Datenbank = | ||
{{:Docker/Datenbank}} | {{:Docker/Datenbank}} | ||
= | = 07 Mounts = | ||
{{:Docker/Mounts}} | {{:Docker/Mounts}} | ||
= | = 08 Multi-Container = | ||
{{:Docker/Multi-Container}} | {{:Docker/Multi-Container}} | ||
= | = 09 Compose = | ||
{{:Docker/Compose}} | {{:Docker/Compose}} | ||
| Zeile 58: | Zeile 35: | ||
{{:Docker/Image-Erstellung}} | {{:Docker/Image-Erstellung}} | ||
= 11 | = 11 Docker-Swarm = | ||
{{:Docker/ | {{:Docker/Swarm}} | ||
<noinclude> | <noinclude> | ||
__KEIN_INHALTSVERZEICHNIS__ | __KEIN_INHALTSVERZEICHNIS__ | ||
[[Kategorie:Skript/Docker]] | |||
[[Kategorie:Seminare/Docker]] | |||
</noinclude> | </noinclude> | ||
Aktuelle Version vom 9. November 2026, 13:48 Uhr
Skript/Docker - Docker verstehen und anwenden
Inhalt
| # | Kapitel | Artikel | Gewichtung |
|---|---|---|---|
| 01 | Überblick | Überblick | 1 |
| 02 | Grundlagen | Grundlagen | 1 |
| 03 | Installation | Installation | 1 |
| 04 | Containerisieren | Containerisieren | 1 |
| 05 | Aktualisieren | Aktualisieren | 1 |
| 06 | Datenbank | Datenbank | 1 |
| 07 | Mounts | Mounts | 1 |
| 08 | Multi-Container | Multi-Container | 1 |
| 09 | Compose | Compose | 1 |
| 10 | Image-Erstellung | Image-Erstellung | 1 |
| 11 | Docker-Swarm | Container-Orchestrierung | 1 |
01 Überblick
02 Grundlagen
Beschreibung
03 Installation
Docker/Installation - Docker auf Debian installieren
Beschreibung
Docker/Engine läuft nativ unter Linux
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 cgroups, Namespaces, Overlay-Dateisystem und Seccomp-Filter |
| Festplattenspeicher | min. 20 GB |
| Internetverbindung | Download von Docker-Images und Paketen |
| Git-Client | SOLLTE installiert sein |
Installation
- Installation aus dem Debian-Repository
sudo apt install docker.io docker-cli docker-compose docker-buildx
Docker-Systemgruppe
- Docker ohne sudo
Um Docker-Befehle ohne sudo verwenden zu können, muss der Benutzer Mitglied der Systemgruppe docker sein
- Gruppe hinzufügen
sudo groupadd docker
- Gruppe beitreten
sudo usermod -aG docker <USER>
04 Containerisieren
Beschreibung
- Containerisieren einer Anwendung eines Dockerfiles
- Zur Erstellung eines Images
- Container starten
- Laufende Anwendung prüfen
- Beispiel
ToDo-Manager der auf Node.js basiert
- JavaScript-Vorkenntnisse sind 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
Syntax
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 auflisten
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
05 Aktualisieren
Beschreibung
- Aktualisieren von Anwendungen
In Docker/Containerisieren wurde eine ToDo-Anwendung containerisiert
- Hier sollen die Anwendung und das Image aktualisiert werden
- Themen
- Image aktualisieren
- Image neu erstellen
- Container stoppen
- Container entfernen
Quellcode aktualisieren
Ändern von "No items yet! Add one above!" in "Sie haben noch keine ToDo-Einträge! Fügen Sie oben einen hinzu!", wenn keine ToDo-Listeneinträge vorhanden sind
Quellcode ändern
- Hilfetext ändern
Ändern Sie in der Datei src/static/js/app.js die Zeile 56, um den neuen leeren Text zu verwenden
- <p className="text-center">No items yet! Add one above!</p>
+ <p className="text-center">Sie haben noch keine ToDo-Einträge! Fügen Sie einen oben hinzu!</p>
Aktualisiertes Images erstellen
docker buildx build -t getting-started .
Aktualisierten Container starten
docker run -dp 3000:3000 getting-started
- Fehlermeldung
docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell
(bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind für <server_ip>:3000 fehlgeschlagen: Port ist bereits vergeben
Fehler tritt auf, wenn Sie den neuen Container zu starten, während der alter Container noch läuft
- Der Grund dafür ist, dass der alte Container bereits den Port 3000 des Hosts verwendet und nur ein Prozess auf dem Rechner (einschließlich Container) auf einen bestimmten Port hören kann.
Um dies zu beheben, müssen Sie den alten Container entfernen
Container entfernen
Um Container zu entfernen, müssen Sie zunächst angehalten werden
- Container-ID ermitteln
docker ps
- Container anhalten
Ersetzen Sie <container-id> durch die ID von docker ps
docker stop <container-id>
- Container entfernen
docker rm <container-id>
- Container mit einem einzigen Befehl stoppen und entfernen
docker rm -f <container-id>
- Container-Namen
Anstelle von Container-ID kann auch der Container-Name verwendet werden
Jeder Container hat eine NAME-Eigenschaft
- Wenn der Benutzer keinen Namen manuell festgelegt hat, generiert Docker einen zufälligen Namen, wobei das erste Wort des Namens ein Adjektiv und das zweite Wort der Nachname eines Wissenschaftlers ist
Aktualisierten Container starten
docker run -dp 3000:3000 getting-started
Aktualisieren Sie Ihren Browser auf <server_ip>:3000 und Sie sollten Ihren aktualisierten Hilfetext sehen
Nächste Schritte
- Images mit anderen teilen
06 Datenbank
Beschreibung
Persistieren einer Datenbank
- Containerdaten persistiert
Beispiel
- Bislang ist die To-do-Liste leer, wenn Sie den Container starten
- Warum ist das so?
- In diesem Kapitel wird dargestellt, wie der Container funktioniert
- Datenbanksysteme
Die meisten Anwendungsprogramme müssen in einer Form Daten speichern
In manchen Fällen reichen dazu simple Dateien aus
- Bei komplexeren Apps, die netzwerk-, multi-user- und transaktionsfähig sein sollen, geht aber kein Weg an einem »richtigen« Datenbank-Management-System (DBMS) vorbei
Dank Docker können Sie sich zumindest für den Test- und Entwicklungsbetrieb die mühsame Konfiguration eines Datenbankservers sparen und stattdessen das gewünschte Datenbanksystem mit wenigen Kommandos bzw. mit ein paar Zeilen in compose.yaml in Betrieb nehmen
- Datenbanksysteme
- Docker/Buch/10 Datenbanken/MySQL und MariaDB
- Docker/Buch/10 Datenbanken/PostgreSQL
- Docker/Buch/10 Datenbanken/MongoDB
- Docker/Buch/10 Datenbanken/Redis
Beispiele
Containers-Dateisystem
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, obwohl sie das gleiche Image verwenden
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
- Ermöglichen, 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
- Letztlich werden beide verwendet, jedoch wird zunächst mit Volume-Mounts begonnen.
Persistieren der ToDo-Daten
- 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
Volume erstellen und Container starten
Sie können das Volume erstellen und den Container über die CLI oder die grafische Oberfläche von Docker Desktop starten.
1. Volume erstellen
docker volume create todo-db
2. Container anhalten und entfernen
- Stoppen und Entfernen des Todo-App-Containers, während er noch kein verwendet
docker rm -f <id>
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
- Sobald der Container hochgefahren ist, öffnen Sie die Anwendung und fügen Sie Ihrer ToDo-Liste einige Einträge hinzu
- Stoppen und entfernen Sie den Container für die Todo-App. Verwenden Sie Docker Desktop oder
docker ps, um die ID zu ermitteln, und danndocker rm -f <id>, um ihn zu entfernen. - Starten Sie einen neuen Container unter Verwendung der vorherigen Schritte
- Öffnen Sie die App. Sie sollten Ihre Objekte immer noch in Ihrer Liste sehen
- Entfernen Sie den Container, wenn Sie mit dem Auschecken Ihrer Liste fertig sind
volume inspect
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
07 Mounts
Skript/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 .
08 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
Konfiguration
Dateien
| Datei | Beschreibung |
|---|---|