Skript/Docker: Unterschied zwischen den Versionen

Aus Foxwiki
Wechseln zu:Navigation, Suche
Keine Bearbeitungszusammenfassung
 
(9 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
; Inhalt
<noinclude>
{{:Seminar/Docker/Inhalte}}
'''Skript/Docker''' - Verstehen und anwenden
 
=== Inhalt ===
{{:Seminar/Linux/Docker/Inhalte}}
 
= 01 Überblick =
= 01 Überblick =
[[Docker]]
{{:Docker}}
{{:Docker}}


= 02 Grundlagen =
= 02 Grundlagen =
[[Docker/Grundlagen]]
{{:Docker/Grundlagen}}
{{:Docker/Grundlagen}}


= 03 Installation =
= 03 Installation =
[[Docker/Installation]]
{{:Docker/Installation}}
{{:Docker/Installation}}


= 04 Containerisieren =
= 04 Containerisieren =
[[Docker/Containerisieren]]
{{:Docker/Containerisieren}}
{{:Docker/Containerisieren}}


= 05 Aktualisieren =
= 05 Aktualisieren =
[[Docker/Aktualisieren]]
{{:Docker/Aktualisieren}}
{{:Docker/Aktualisieren}}


= 06 Datenbank =
= 06 Datenbank =
[[Docker/Datenbank]]
{{:Docker/Datenbank}}
{{:Docker/Datenbank}}


= 07 Mounts =
= 07 Mounts =
[[Docker/Mounts]]
{{:Docker/Mounts}}
{{:Docker/Mounts}}


= 08 Multi-Container =
= 08 Multi-Container =
[[Docker/Multi-Container]]
{{:Docker/Multi-Container}}
{{:Docker/Multi-Container}}


= 09 Compose =
= 09 Compose =
[[Docker/Compose]]
{{:Docker/Compose}}
{{:Docker/Compose}}


= 10 Image-Erstellung =
= 10 Image-Erstellung =
[[Docker/Image-Erstellung]]
{{:Docker/Image-Erstellung}}
{{:Docker/Image-Erstellung}}


= 11 Docker-Swarm =
= 11 Docker-Swarm =
[[Docker/Swarm]]
{{:Docker/Swarm}}
{{:Docker/Swarm}}


= 12 Ausblick =
= 12 Ausblick =
[[Docker/Ausblick]]
{{:Docker/Ausblick}}
{{:Docker/Ausblick}}


Zeile 42: Zeile 61:
__KEIN_INHALTSVERZEICHNIS__
__KEIN_INHALTSVERZEICHNIS__
</noinclude>
</noinclude>
[[Kategorie:Seminar/Docker]]

Aktuelle Version vom 12. Oktober 2026, 14:54 Uhr

Skript/Docker - Verstehen und anwenden

Inhalt

Seminar/Linux/Docker/Inhalte

01 Überblick

Docker


02 Grundlagen

Docker/Grundlagen


Beschreibung

03 Installation

Docker/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

Docker/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

  1. from
  2. workdir
  3. copy
  4. run
  5. cmd
  6. expose

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 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

Docker/Aktualisieren

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


05 Aktualisieren

Docker/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

Docker/Freigeben



06 Datenbank

Docker/Datenbank


Beschreibung

Persistieren einer Datenbank

Beispiel
  • Bis lang ist die To-do-Liste leer, wenn Sie den Container starten
  • Warum ist das so?
  • In diesem Kapitel wird dargestellt, wie der Container funktioniert

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 --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
  • 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
<code>docker rm -f <id></code>

3.&nbsp;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 <code>/etc/todos</code> im Container, wodurch alle Dateien, die unter dem Pfad erstellt werden, erfasst werden

<syntaxhighlight lang="bash" highlight="1" line copy>
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

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

Zusammenfassung

In diesem Abschnitt haben Sie gelernt, wie man Containerdaten persistiert


07 Mounts

Docker/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=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 .

08 Multi-Container

Docker/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

Konfiguration

Dateien

Datei Beschreibung


09 Compose

Docker/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:

Parameter

Entsprechung zwischen Parametern von docker run und YAML-Direktiven in compose.yaml

  • So kann nachvollzogen werden, wie Docker Compose die 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.

Anwendungsstack starten

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

Projekt

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

10 Image-Erstellung

Docker/Image-Erstellung Docker/Image-Erstellung

11 Docker-Swarm

Docker/Swarm Docker/Swarm

12 Ausblick

Docker/Ausblick Docker/Ausblick - Weitere Schritte und Bereiche

Beschreibung

Container-Orchestrierung

Betrieb von Containern in der Produktion ist schwierig
  • Sie wollen sich nicht in einen Rechner einloggen und einfach einen Docker-Run oder Docker-Compose ausführen
  • Und warum nicht? Was passiert, wenn die Container sterben? Wie skalieren Sie über mehrere Rechner hinweg? Die Container-Orchestrierung löst dieses Problem
  • Tools wie Kubernetes, Swarm, Nomad und ECS helfen alle bei der Lösung dieses Problems, alle auf leicht unterschiedliche Weise
Manager

Die allgemeine Idee ist, dass Sie Manager haben, die den erwarteten Zustand erhalten

  • Dieser Zustand könnte lauten: "Ich möchte zwei Instanzen meiner Webanwendung ausführen und Port 80 freigeben"
  • Die Manager sehen sich dann alle Maschinen im Cluster an und delegieren die Arbeit an Arbeitsknoten
  • Die Manager achten auf Änderungen (z. B&.nbsp;das Beenden eines Containers) und sorgen dann dafür, dass der tatsächliche Zustand dem erwarteten Zustand entspricht

Cloud Native Computing Foundation

Projekte

Die CNCF ist eine herstellerneutrale Heimat für verschiedene Open-Source-Projekte, darunter Kubernetes, Prometheus, Envoy, Linkerd, NATS und andere

Container von Grund auf erstellen

Wenn Sie sehen möchten, wie Container von Grund auf gebaut werden, hat Liz Rice von Aqua Security einen fantastischen Vortrag, in dem sie einen Container von Grund auf in Go erstellt

  • Obwohl der Vortrag nicht auf Netzwerke, die Verwendung von Images für das Dateisystem und andere fortgeschrittene Themen eingeht, gibt er einen tiefen Einblick in die Funktionsweise