Zum Inhalt springen

Docker/Multi-Container: Unterschied zwischen den Versionen

Aus Foxwiki
Keine Bearbeitungszusammenfassung
K Textersetzung - „Docker/Workshop“ durch „Docker“
 
(29 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
== Multi-Container ==
'''Docker/Multi-Container''' - Multi-Container
; Multi-Container-Anwendungen
Bis zu diesem Punkt haben Sie mit Einzelcontaineranwendungen gearbeitet. Aber jetzt werden Sie dem Anwendungsstapel MySQL hinzufügen. Dabei stellt sich oft die Frage: "Wo wird MySQL ausgeführt? Soll es im gleichen Container installiert oder separat ausgeführt werden?" Im Allgemeinen sollte jeder Container eine Aufgabe erfüllen, und zwar eine gute. Im Folgenden werden einige Gründe genannt, die dafür sprechen, den Container separat zu betreiben
* Es ist gut möglich, dass Sie APIs und Front-Ends anders skalieren müssen als Datenbanken
* Separate Container ermöglichen eine isolierte Versionierung und Aktualisierung der Versionen
* Während Sie lokal einen Container für die Datenbank verwenden können, möchten Sie in der Produktion vielleicht einen verwalteten Dienst für die Datenbank nutzen. Sie möchten Ihre Datenbank-Engine dann nicht mit Ihrer Anwendung ausliefern
* Die Ausführung mehrerer Prozesse erfordert einen Prozessmanager (der Container startet nur einen Prozess), was die Komplexität beim Starten und Herunterfahren des Containers erhöht


Und es gibt noch mehr Gründe. Wie das folgende Diagramm zeigt, ist es also am besten, Ihre Anwendung in mehreren Containern laufen zu lassen
== 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.


=== [https://docs.docker.com/get-started/workshop/07_multi_container/#container-networking Container-Vernetzung] ===
* Entwurfsprinzip. Ein Container = eine klar abgegrenzte Aufgabe.
Bedenken Sie, dass Container standardmäßig isoliert laufen und nichts über andere Prozesse oder Container auf demselben Rechner wissen. Wie kann man also einem Container erlauben, mit einem anderen zu kommunizieren? Die Antwort ist Networking. Wenn Sie die beiden Container in dasselbe Netzwerk einbinden, können sie miteinander kommunizieren


=== [https://docs.docker.com/get-started/workshop/07_multi_container/#start-mysql MySQL starten] ===
Anwendungsteile bleiben lose gekoppelt, Images bleiben ''kompakt und wartbar''.
Es gibt zwei Möglichkeiten, einen Container in ein Netzwerk einzubinden
* Weisen Sie das Netzwerk beim Starten des Containers zu
* Verbinden Sie einen bereits laufenden Container mit einem Netzwerk


In den folgenden Schritten werden Sie zuerst das Netzwerk erstellen und dann den MySQL-Container beim Start verbinden.# Erstellen Sie das Netzwerk
; Vorteile:


* docker network create todo-app
* 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.


* Starten Sie einen MySQL-Container und verbinden Sie ihn mit dem Netzwerk. Sie werden auch ein paar Umgebungsvariablen definieren, die die Datenbank zur Initialisierung der Datenbank verwenden wird. Um mehr über die MySQL-Umgebungsvariablen zu erfahren, lesen Sie den Abschnitt "Environment Variables" im [https://hub.docker.com/_/mysql/ MySQL Docker Hub Listing]
; 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).


docker run -d \
== Container-Vernetzung ==
[[Datei:Docker MultiContainer.png|mini|400px|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.


--network todo-app --network-alias mysql \
==  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


-v todo-mysql-data:/var/lib/mysql \
In diesem Abschnitt wird zuerst ein Netzwerk erstellt und der MySQL-Container beim Start daran angeschlossen.
* Erstellen Sie das Netzwerk


-e MYSQL_ROOT_PASSWORD=secret \
<syntaxhighlight lang="bash" highlight="1" line copy>
docker network create todo-app
</syntaxhighlight>
* MySQL-Container starten und mit dem Netzwerk verbinden. Dabei werden Umgebungsvariablen gesetzt, die MySQL für die Initialisierung verwendet.


-e MYSQL_DATENBANK=todos \
<syntaxhighlight lang="bash" line copy>
 
docker run -d \
mysql:8.0
    --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
</syntaxhighlight>


Im vorherigen Befehl sehen Sie die --network-alias-Flagge. In einem späteren Abschnitt werden Sie mehr über dieses Flag erfahren.* Tipp
Im vorherigen Befehl sehen Sie die --network-alias-Flagge. In einem späteren Abschnitt werden Sie mehr über dieses Flag erfahren.'''(!)'''


Im obigen Befehl sehen Sie ein Volume namens todo-mysql-data, das unter /var/lib/mysql gemountet ist, wo MySQL seine Daten speichert. Sie haben jedoch nie den Befehl docker volume create ausgeführt. Docker erkennt, dass Sie ein benanntes Volume verwenden möchten und erstellt dieses automatisch für Sie.* Um zu bestätigen, dass die Datenbank funktioniert, stellen Sie eine Verbindung zur Datenbank her und überprüfen Sie, ob sie sich verbindet
; 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
<syntaxhighlight lang="bash" highlight="1" line copy>
docker exec -it <mysql-container-id> mysql -u root -p
docker exec -it <mysql-container-id> mysql -u root -p
</syntaxhighlight>


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
: Wenn die Passwortabfrage erscheint, geben Sie ''secret'' ein.  


mysql> DATENBANKEN ANZEIGEN;
* Führen Sie in der MySQL-Shell eine Liste der Datenbanken auf und überprüfen Sie, ob die Datenbank todos angezeigt wird


Sie sollten eine Ausgabe sehen, die wie folgt aussieht
<syntaxhighlight lang="mysql">
* +--------------------+
mysql> SHOW DATABASES;
 
</syntaxhighlight>
| Datenbank |


<syntaxhighlight lang="mysql">
+--------------------+
| Datenbank          |
+--------------------+
+--------------------+
| information_schema |
| information_schema |
 
| mysql             |
| mysql |
 
| performance_schema |
| performance_schema |
 
| sys               |
| sys |
| todos             |
 
| todos |
 
+--------------------+
+--------------------+
5 Zeilen im Satz (0.00 sec)
</syntaxhighlight>


5 Zeilen im Satz (0.00 sec)* Beenden Sie die MySQL-Shell, um zur Shell auf Ihrem Rechner zurückzukehren
* Beenden Sie die MySQL-Shell, um zur Shell auf Ihrem Rechner zurückzukehren
 
<syntaxhighlight lang="mysql">
# mysql> exit
mysql> exit
 
</syntaxhighlight>
Sie haben jetzt eine todos-Datenbank und können sie benutzen
Sie haben jetzt eine todos-Datenbank und können sie benutzen


=== [https://docs.docker.com/get-started/workshop/07_multi_container/#connect-to-mysql Verbindung zu MySQL herstellen] ===
== Verbindung zu MySQL herstellen ==
Jetzt, wo Sie wissen, dass MySQL läuft, können Sie es benutzen. Aber wie benutzen Sie es? Wenn Sie einen anderen Container im selben Netzwerk betreiben, wie finden Sie den Container? Denken Sie daran, dass jeder Container seine eigene IP-Adresse hat
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.


Um die obigen Fragen zu beantworten und die Container-Netzwerke besser zu verstehen, werden Sie den nicolaka/netshoot-Container verwenden, der eine Reihe von Werkzeugen enthält, die für die Fehlersuche und das Debuggen von Netzwerkproblemen nützlich sind.# Starten Sie einen neuen Container mit dem nicolaka/netshoot-Image. Stellen Sie sicher, dass er mit demselben Netzwerk verbunden ist
* Netshoot-Container im selben Netzwerk starten


* docker run -it --network todo-app nicolaka/netshoot
<syntaxhighlight lang="bash" highlight="1" line copy>
docker run -it --network todo-app nicolaka/netshoot
</syntaxhighlight>


* Innerhalb des Containers verwenden Sie den Befehl dig, ein nützliches DNS-Tool. Sie werden die IP-Adresse für den Hostnamen mysql nachschlagen
* Im Container DNS-Auflösung für den Hostnamen mysql testen


<syntaxhighlight lang="bash" highlight="1" line copy>
dig mysql
dig mysql
</syntaxhighlight>


Sie sollten eine Ausgabe wie die folgende erhalten.# <nowiki>; <<>> DiG 9.18.8 <<>> mysql</nowiki>
Das Ergebnis sollte in etwa wie folgt aussehen:


<nowiki>;; globale Optionen: +cmd</nowiki>
<syntaxhighlight lang="console">
; <<>> 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


<nowiki>;; Antwort erhalten:</nowiki>
;; QUESTION SECTION:
;mysql. IN A


<nowiki>;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162</nowiki>
;; ANSWER SECTION:
mysql. 600 IN A 172.23.0.2


<nowiki>;; Flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTORITAET: 0, ZUSAETZLICH: 0</nowiki>
;; 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
</syntaxhighlight>


<nowiki>;; FRAGEABSCHNITT:</nowiki>
* 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.


<nowiki>;mysql. </nowiki>IN A
* 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.


<nowiki>;; ANTWORT-ABSCHNITT:</nowiki>
Anwendungen im selben Docker-Netzwerk verbinden sich daher einfach mit dem Hostnamen mysql.


mysql. 600 IN A 172.23.0.2
== Starten Sie Ihre Anwendung mit MySQL ==
 
<nowiki>;; Abfragezeit: 0 msec</nowiki>
 
<nowiki>;; SERVER: 127.0.0.11#53(127.0.0.11)</nowiki>
 
<nowiki>;; WHEN: Tue Oct 01 23:47:24 UTC 2019</nowiki>
 
<nowiki>;; MSG SIZE rcvd: 44</nowiki>
 
Im "ANTWORTABSCHNITT" sehen Sie einen A-Eintrag für mysql, der zu 172.23.0.2 aufgelöst wird (Ihre IP-Adresse wird höchstwahrscheinlich einen anderen Wert haben). Obwohl mysql normalerweise kein gültiger Hostname ist, war Docker in der Lage, ihn in die IP-Adresse des Containers aufzulösen, der diesen Netzwerkalias hatte. Erinnern Sie sich daran, dass Sie zuvor den --network-alias verwendet haben
 
Das bedeutet, dass Ihre Anwendung lediglich eine Verbindung zu einem Host namens mysql herstellen muss, damit sie mit der Datenbank kommunizieren kann
 
=== [https://docs.docker.com/get-started/workshop/07_multi_container/#run-your-app-with-mysql Starten Sie Ihre Anwendung mit MySQL] ===
Die todo-App unterstützt das Setzen einiger Umgebungsvariablen, um die MySQL-Verbindungseinstellungen festzulegen. Diese sind
Die todo-App unterstützt das Setzen einiger Umgebungsvariablen, um die MySQL-Verbindungseinstellungen festzulegen. Diese sind
* MYSQL_HOST - der Hostname für den laufenden MySQL-Server
{| class="wikitable sortable options big"
* MYSQL_USER - der Benutzername, der für die Verbindung verwendet werden soll
|-
* MYSQL_PASSWORD - das Passwort, das für die Verbindung verwendet werden soll
! Parameter !! Beschreibung
* MYSQL_DB - die zu verwendende Datenbank nach der Verbindung
|-
| 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
|-
|}


Hinweis
; 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.


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. Diogo Monica, ein ehemaliger Leiter der Sicherheitsabteilung bei Docker, [https://blog.diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/ hat einen fantastischen Blogbeitrag geschrieben], der erklärt, warum
;Erstellen eines MYSQL-Containers


Ein sicherer Mechanismus besteht darin, die von Ihrem Container-Orchestrierungs-Framework bereitgestellte Unterstützung für Geheimnisse zu verwenden. In den meisten Fällen werden diese Geheimnisse als Dateien in den laufenden Container eingebunden. Sie werden sehen, dass viele Anwendungen (einschließlich des MySQL-Images und der todo-App) auch env vars mit einem _FILE-Suffix unterstützen, um auf eine Datei zu verweisen, die die Variable enthält
* 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
 
Wenn Sie zum Beispiel die Variable MYSQL_PASSWORD_FILE setzen, wird die Anwendung den Inhalt der referenzierten Datei als Verbindungspasswort verwenden. Docker tut nichts, um diese Umgebungsvariablen zu unterstützen. Ihre Anwendung muss wissen, dass sie nach der Variable suchen und den Inhalt der Datei abrufen muss
 
Sie können nun Ihren entwicklungsfähigen Container starten.# 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 127.0.0.1:3000:3000 \


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


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


<syntaxhighlight lang="mysql">
nodemon src/index.js
[nodemon] 2.0.20
[nodemon] 2.0.20
[nodemon] um jederzeit neu zu starten, geben Sie `rs` ein
[nodemon] um jederzeit neu zu starten, geben Sie `rs` ein
[nodemon] überwachte(s) Verzeichnis(e): *.*
[nodemon] überwachte(s) Verzeichnis(e): *.*
[nodemon] startet `node src/index.js`
[nodemon] startet `node src/index.js`
Verbunden mit der mysql db auf dem Host mysql
Verbunden mit der mysql db auf dem Host mysql
Überwacht auf Port 3000
</syntaxhighlight>


Überwacht auf Port 3000* Öffnen Sie die Anwendung in Ihrem Browser und fügen Sie Ihrer ToDo-Liste ein paar Einträge hinzu
* Ö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
* 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


<syntaxhighlight lang="bash" highlight="1" line copy>
docker exec -it <mysql-container-id> mysql -p todos
docker exec -it <mysql-container-id> mysql -p todos
</syntaxhighlight>


Und in der mysql-Shell führen Sie Folgendes aus:# mysql> select * from todo_items;
Und in der mysql-Shell führen Sie Folgendes aus:
<syntaxhighlight lang="mysql">
mysql> select * from todo_items;


+--------------------------------------+--------------------+-----------+
+--------------------------------------+--------------------+-----------+
Zeile 177: Zeile 202:


+--------------------------------------+--------------------+-----------+
+--------------------------------------+--------------------+-----------+
</syntaxhighlight>


Deine Tabelle sieht anders aus, weil sie deine Artikel enthält. Aber Sie sollten sie dort gespeichert sehen
Deine Tabelle sieht anders aus, weil sie deine Artikel enthält. Aber Sie sollten sie dort gespeichert sehen


=== [https://docs.docker.com/get-started/workshop/07_multi_container/#summary Zusammenfassung] ===
== Zusammenfassung ==
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
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


Verwandte Informationen
== Nächste Schritte ==
* [https://docs.docker.com/reference/cli/docker/ Docker CLI-Referenz]
Im nächsten Abschnitt wird eine etwas bequemere Methode zur Interaktion von Containern mit [[Docker/Compose|Docker Compose]] vorgestellt.
* [https://docs.docker.com/engine/network/ Überblick über das Networking]
 
== Anhang ==
=== Siehe auch ===
<div style="column-count:2">
<categorytree hideroot=on mode="pages">Docker</categorytree>
</div>
----
{{Special:PrefixIndex/{{BASEPAGENAME}}/}}


=== [https://docs.docker.com/get-started/workshop/07_multi_container/#next-steps Nächste Schritte] ===
=== Dokumentation ===
Es ist gut möglich, dass Sie sich langsam ein wenig überfordert fühlen mit dem, was Sie tun müssen, um diese Anwendung zu starten. Sie müssen ein Netzwerk erstellen, Container starten, alle Umgebungsvariablen angeben, Ports freischalten und vieles mehr. Das ist eine Menge, die man sich merken muss, und es macht es sicherlich schwieriger, die Dinge an jemand anderen weiterzugeben
<!--
; Man-Page
# [https://manpages.debian.org/stable/procps/pgrep.1.de.html prep(1)]


Im nächsten Abschnitt werden Sie etwas über Docker Compose erfahren. Mit Docker Compose können Sie Ihre Anwendungsstapel auf viel einfachere Weise weitergeben und andere mit einem einzigen, einfachen Befehl in Betrieb nehmen lassen
; Info-Pages
-->


[https://docs.docker.com/get-started/workshop/08_using_compose/ Docker Compose verwenden]
=== Links ===
==== Projekt ====
==== Weblinks ====
# [https://hub.docker.com/_/mysql/ MySQL Docker Hub Listing]
# [https://docs.docker.com/reference/cli/docker/ Docker CLI-Referenz]
# [https://docs.docker.com/engine/network/ Überblick über das Networking]


[[Kategorie:Docker/Workshop]]
[[Kategorie:Docker]]

Aktuelle Version vom 3. November 2025, 17:52 Uhr

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

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;
+--------------------+
| Datenbank          |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| todos              |
+--------------------+
5 Zeilen im Satz (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 127.0.0.1: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] um jederzeit neu zu starten, geben Sie `rs` ein
[nodemon] überwachte(s) Verzeichnis(e): *.*
[nodemon] startet `node src/index.js`
Verbunden mit der mysql db auf dem Host mysql
Überwacht auf 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

Zusammenfassung

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

Nächste Schritte

Im nächsten Abschnitt wird eine etwas bequemere Methode zur Interaktion von Containern mit Docker Compose vorgestellt.

Anhang

Siehe auch



Dokumentation

Links

Projekt

Weblinks

  1. MySQL Docker Hub Listing
  2. Docker CLI-Referenz
  3. Überblick über das Networking