Wenn Sie Docker verwenden, um Ihre Anwendungen zu containerisieren, ist es üblich, jede Komponente der Anwendung in einem separaten Container auszuführen. Beispielsweise kann eine Website einen Webserver, eine Anwendung und eine Datenbank haben, die jeweils in einem eigenen Container ausgeführt werden.
Die Konfiguration der Container für die Kommunikation untereinander und mit dem Hostcomputer kann eine Herausforderung darstellen. Dieser Leitfaden verwendet eine einfache Beispiel-App, um die Grundlagen der Docker-Container-Kommunikation zu demonstrieren. Die App besteht aus einer Node.js-App, die Daten aus einer PostgreSQL-Datenbank liest.
Bevor Sie beginnen
Installieren Sie Docker CE
Sie benötigen einen Linode mit installiertem Docker CE, um den Schritten in dieser Anleitung zu folgen.
Um Docker CE (Community Edition) zu installieren, befolgen Sie die Anweisungen in einer der folgenden Anleitungen:
-
Installieren und Verwenden von Docker unter Ubuntu und Debian
-
Installieren und Verwenden von Docker unter CentOS und Fedora
Vollständige Anweisungen zu noch mehr Linux-Distributionen finden Sie im Abschnitt „Install Docker Engine“ der offiziellen Docker-Dokumentation.
Beispiel-Node.js-Anwendung
Die in diesem Handbuch verwendete Beispiel-App ist eine einfache Node.js-App, die „Hello World“ aus einer PostgreSQL-Datenbank liest und auf der Konsole ausgibt. In diesem Abschnitt werden Sie die App auf Ihrem Linode erstellen und testen, ohne Container zu verwenden.
PostgreSQL installieren und konfigurieren
-
Aktualisieren Sie Ihr System:
sudo apt update && sudo apt upgrade
-
Installieren Sie PostGreSQL:
sudo apt install postgresql postgresql-contrib
-
Ändere das
postgres
Benutzerpasswort:sudo passwd postgres
-
Legen Sie ein Passwort für
postgres
fest Datenbankbenutzer:su - postgres psql -d template1 -c "ALTER USER postgres WITH PASSWORD 'newpassword';"
-
Erstellen Sie eine Datenbank für die Beispiel-App und verbinden Sie sich damit:
createdb nodejs psql nodejs
-
Fügen Sie „Hallo Welt“ zur Datenbank hinzu:
nodejs=# CREATE TABLE hello (message varchar); nodejs=# INSERT INTO hello VALUES ('Hello world'); nodejs=# \q
-
Erstellen Sie einen Dump der Datenbank zur späteren Verwendung:
pg_dumpall > backup.sql
-
Melden Sie sich als
postgres
ab Linux-Benutzer:exit
-
Kopieren Sie den Daten-Dump in Ihr Home-Verzeichnis:
sudo cp /var/lib/postgresql/backup.sql ~/.
-
Da Sie sich von einem Container aus mit dieser Datenbank verbinden (der eine andere IP-Adresse als
locahost
haben wird ), müssen Sie die PostgreSQL-Konfigurationsdatei bearbeiten, um Verbindungen von entfernten Adressen zuzulassen. Öffnen Sie/etc/postgresql/9.5/main/postgresql.conf
in einem Texteditor. Entkommentieren Sie dielisten_addresses
Zeile und setzen Sie es auf '*':- Datei:/ etc/postgresql/9.5/main/postgresql.conf
1 2 3 4 5 6 7
#------------------------------------------------------------------------------ # CONNECTIONS AND AUTHENTICATION #------------------------------------------------------------------------------ # - Connection Settings - listen_addresses = '*' # what IP address(es) to listen on;
-
Aktivieren und starten Sie
postgresql
Dienst:sudo systemctl enable postgresql sudo systemctl start postgresql
Eine Hello-World-App erstellen
-
Knoten und NPM installieren:
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - sudo apt-get install nodejs
-
Navigieren Sie zum Home-Verzeichnis und erstellen Sie ein Verzeichnis:
cd mkdir app && cd app
-
Erstellen Sie mit einem Texteditor
app.js
und fügen Sie den folgenden Inhalt hinzu:- Datei:app .js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
const { Client } = require('pg') const client = new Client({ user: 'postgres', host: 'localhost', database: 'nodejs', password: 'newpassword', port: 5432 }) client.connect() client.query('SELECT * FROM hello', (err, res) => { console.log(res.rows[0].message) client.end() })
Diese App verwendet den
pg
NPM-Modul (node-postgres) zum Herstellen einer Verbindung mit der im vorherigen Abschnitt erstellten Datenbank. Anschließend fragt es die „Hello“-Tabelle ab (die die „Hello World“-Nachricht zurückgibt) und protokolliert die Antwort an der Konsole. Ersetzen Sie'newpassword'
mit dempostgres
Datenbankbenutzerpasswort, das Sie im vorherigen Abschnitt festgelegt haben.Hinweis Das
pg
-Modul kann auch Umgebungsvariablen verwenden, um die Client-Verbindung zu konfigurieren. Dies ist die empfohlene Option für Produktions-Apps. Lesen Sie mehr über Umgebungsvariablen in der Node-Postgres-Dokumentation. -
Installieren Sie das
pg
Modul:npm install pg
-
Testen Sie die App:
node app.js
Wenn die Datenbank richtig konfiguriert ist, wird „Hello World“ auf der Konsole angezeigt.
Container mit Docker-Host verbinden
Dieser Abschnitt veranschaulicht einen Anwendungsfall, bei dem die Node.js-App von einem Docker-Container ausgeführt wird und eine Verbindung zu einer Datenbank herstellt, die auf dem Docker-Host ausgeführt wird.
Docker-Container einrichten
-
Kehren Sie zu Ihrem Home-Verzeichnis zurück:
cd
-
Erstellen Sie ein Dockerfile zum Ausführen der Node.js-App:
- Datei:Dockerfile
1 2 3 4 5 6 7
FROM debian RUN apt update -y && apt install -y gnupg curl RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && apt install -y nodejs COPY app/ /home/ ENTRYPOINT tail -F /dev/null
-
Das aus diesem Dockerfile erstellte Image kopiert die
app/
Verzeichnis zum neuen Image. Bearbeiten Sieapp.js
damit die App eine Verbindung zurdatabase
herstellen kann host anstelle vonlocalhost
:- Datei:app /app.js
1 2 3 4 5 6 7
const client = new Client({ user: 'postgres', host: 'database', database: 'nodejs', password: 'newpassword', port: 5432 })
-
Erstellen Sie ein Image aus der Docker-Datei:
docker build -t node_image .
Container mit Datenbank verbinden
-
Docker richtet automatisch ein standardmäßiges Bridge-Netzwerk ein , auf die über
docker0
zugegriffen wird Netzwerkschnittstelle. Verwenden Sieifconfig
oderip
um diese Schnittstelle anzuzeigen:ifconfig docker0
Die Ausgabe sieht wie folgt aus:
Die interne IP-Adresse des Docker-Hosts (Ihres Linode) ist 172.17.0.1.docker0 Link encap:Ethernet HWaddr 02:42:1e:e8:39:54 inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:1eff:fee8:3954/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3848 errors:0 dropped:0 overruns:0 frame:0 TX packets:5084 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:246416 (246.4 KB) TX bytes:94809688 (94.8 MB)
-
Erlauben Sie PostgreSQL, Verbindungen von der Docker-Schnittstelle zu akzeptieren. Öffnen Sie
/etc/postgresql/9.5/main/pg_hba.conf
in einem Texteditor und fügen Sie die folgende Zeile hinzu:- Datei:/ etc/postgresql/9.5/main/pg_hba.conf
1
host all postgres 172.17.0.0/16 password
Da 172.17.0.1 die IP des Docker-Hosts ist, haben alle Container auf dem Host eine IP-Adresse im Bereich 172.17.0.0/16.
-
Starten Sie die Datenbank neu:
sudo systemctl restart postgresql
-
Container starten:
docker run -d --add-host=database:172.17.0.1 --name node_container node_image
Der
--add-host
Option definiert einedatabase
host, der auf die IP-Adresse des Docker-Hosts verweist. Deklarieren derdatabase
Host zur Laufzeit, anstatt die IP-Adresse in der App fest zu codieren, trägt dazu bei, dass der Container wiederverwendbar bleibt. -
Verwenden Sie innerhalb des Containers
ping
um die Verbindung zurdatabase
zu testen Host:docker exec -it node_container ping database
-
Jedem Docker-Container wird außerdem eine eigene IP-Adresse innerhalb des Blocks 172.17.0.0/16 zugewiesen. Finden Sie die IP-Adresse dieses Containers mit
ip
:docker exec -it node_container ip addr show eth0
Sie können diese Verbindung testen, indem Sie diese Adresse vom Docker-Host aus anpingen.
-
Führen Sie die App aus:
docker exec -it node_container node home/app.js
Wenn die Konfiguration erfolgreich war, sollte das Programm wie zuvor die Konsolenausgabe „Hello World“ anzeigen.
Zwei Container verbinden
In diesem Abschnitt werden sowohl die App als auch die Datenbank in separaten Containern ausgeführt. Sie können das offizielle Postgres-Image von Docker Hub verwenden und den zuvor erstellten SQL-Dump laden.
Achtung Sie sollten keine Produktionsdatenbankdaten in einem Docker-Container speichern. Container sollten als kurzlebige Einheiten behandelt werden:Wenn ein Container unerwartet abstürzt oder neu gestartet wird, gehen alle Daten in der Datenbank verloren.
-
Beenden und entfernen Sie den Node.js-Container:
docker stop node_container docker rm node_container
-
Ziehen Sie das
postgres
Bild:docker pull postgres
-
Stellen Sie sicher, dass Ihre
backup.sql
Datei in Ihrem aktuellen Arbeitsverzeichnis befindet, führen Sie dannpostgres
aus Bild:docker run -d -v `pwd`:/backup/ --name pg_container postgres
Das
-v
Option hängt Ihr aktuelles Arbeitsverzeichnis in/backup/
ein Verzeichnis auf dem neuen Container. -
Der neue Container startet automatisch die Postgres-Datenbank und erstellt den Postgres-Benutzer. Geben Sie den Container ein und laden Sie den SQL-Dump:
docker exec -it pg_container bash cd backup psql -U postgres -f backup.sql postgres exit
-
Führen Sie das Knoten-Image erneut aus. Diesmal statt
--add-host
verwenden Sie den--link
Option zum Verbinden des Containers mit pg_container:docker run -d --name node_container --link=pg_container:database node_image
Dadurch wird der
pg_container
verknüpft unter dem Hostnamendatabase
. -
Öffnen Sie
/etc/hosts
in node_container, um zu bestätigen, dass der Link hergestellt wurde:docker exec -it node_container cat /etc/hosts
Es sollte eine Zeile ähnlich der folgenden vorhanden sein:
- Datei:/ etc/hosts
172.17.0.2 database pg_container
Dies zeigt, dass
pg_container
wurde der IP-Adresse 172.17.0.2 zugewiesen und ist über den Hostnamendatabase
mit diesem Container verknüpft , wie erwartet. -
Da die Node.js-App immer noch erwartet, eine Verbindung zu einer PostgreSQL-Datenbank auf der
database
herzustellen host, es sind keine weiteren Änderungen notwendig. Sie sollten die App wie zuvor ausführen können:docker exec -it node_container node home/app.js
Verwendung von Docker Compose
Verwenden Sie den --link
oder --host
Optionen jedes Mal, wenn Sie Ihre Container starten, können umständlich sein. Wenn Ihr Server oder einer der Container abstürzt, müssen sie manuell neu verbunden werden. Dies ist keine ideale Situation für Anwendungen, die eine ständige Verfügbarkeit erfordern. Glücklicherweise bietet Docker Docker Compose um mehrere Container zu verwalten und sie automatisch miteinander zu verknüpfen, wenn sie gestartet werden. In diesem Abschnitt wird Docker Compose verwendet, um die Ergebnisse des vorherigen Abschnitts zu reproduzieren.
Hinweis Für eine umfassendere Erklärung von Docker Compose und wie man docker-compose.yml
schreibt Konfigurationsdateien finden Sie in unserem vollständigen Docker Compose-Leitfaden.
-
Installieren Sie Docker Compose:
sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
-
Erstellen Sie im selben Verzeichnis wie Ihr Dockerfile eine
docker-compose.yml
Datei mit folgendem Inhalt:- Datei:docker -compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
version: '3' services: database: image: postgres container_name: pg_container volumes: - pgdata:/var/lib/postgresql/data app: build: . container_name: node_container links: - database environment: - PGPASSWORD=newpassword - PGUSER=postgres - PGDATABASE=nodejs - PGHOST=database - PGPORT=5432 depends_on: - database volumes: pgdata: {}
Wenn Sie Docker Compose mit dieser Datei ausführen, wird der
pg_container
erstellt undnode_container
aus dem vorherigen Abschnitt. Wie zuvor verwendet der Datenbankcontainer das offizielle PostgreSQL-Image, während der App-Container aus Ihrem Dockerfile erstellt wird. Dielinks
Der Eintrag hat die gleiche Funktion wie der--link
Option inrun
zuvor verwendeter Befehl. -
Mit Docker Compose können Sie auch Umgebungswerte einrichten, sodass Sie die App vereinfachen können, diese zu verwenden, anstatt die Werte fest codiert zu haben. Bearbeiten Sie
app.js
um diese Werte zu entfernen:- Datei:app .js
1 2 3 4 5 6 7 8 9 10 11
const express = require('express') const { Client } = require('pg') const client = new Client() client.connect() client.query('SELECT * FROM hello', (err, res) => { console.log(res.rows[0].message) client.end() })
-
Entfernen Sie die vorherigen Container:
docker rm -f node_container pg_container
-
Verwenden Sie Docker Compose, um die Container aufzurufen:
docker-compose up -d
-
Laden Sie die Beispieldaten in den neuen Container:
docker cp backup.sql pg_container:/ docker exec -it pg_container psql -U postgres -f backup.sql postgres
-
Führen Sie
app.js
aus aus dem App-Container:docker exec -it node_container node home/app.js
Die App sollte wie zuvor laufen.
Schlussfolgerung
Standardmäßig weist Docker jedem Container und dem Docker-Host automatisch eine IP-Adresse zu. Sie können Dienste zwischen Containern manuell verbinden, indem Sie diese Adressen verwenden (vorausgesetzt, Ihre Firewall lässt die Verbindung zu).
Docker bietet jedoch auch eine Reihe praktischer Wrapper um diese Verbindungen, die Ihnen helfen, den Verbindungsprozess zu beschleunigen und zu vereinfachen. Sie können Ihren Docker-Host mit einem Container mit einem eindeutigen Hostnamen verbinden oder zwei Container direkt verknüpfen. Die Verwendung von Docker Compose kann diesen Prozess noch weiter vereinfachen, indem Sie Verbindungen in docker-compose.yml
deklarieren können Datei, sodass sie automatisch erstellt werden, wenn die Container aufgerufen werden.
Es gibt andere Verbindungsoptionen, die in diesem Handbuch nicht behandelt wurden. Beispielsweise können Sie einen Container mit --net="host"
ausführen , der den Netzwerkstapel dieses Containers mit dem Docker-Host teilt:localhost
auf dem Container zeigt auf localhost
auf dem Docker-Host. Sie können auch Ports für jeden Docker-Container verfügbar machen oder das standardmäßige Bridge-Netzwerk für mehr Flexibilität konfigurieren. Eine eingehendere Diskussion dieser Optionen finden Sie unter den Links im Abschnitt "Weitere Informationen" weiter unten.
Weitere Informationen
Weitere Informationen zu diesem Thema finden Sie in den folgenden Ressourcen. Obwohl diese in der Hoffnung bereitgestellt werden, dass sie nützlich sind, beachten Sie bitte, dass wir nicht für die Genauigkeit oder Aktualität extern gehosteter Materialien garantieren können.
- Docker:Container-Kommunikation verstehen
- Container verknüpfen
- Container verbinden