Zugriff auf einen Docker-Container von einem anderen Container aus


79

Ich habe zwei Docker-Container basierend auf zwei verschiedenen Bildern erstellt. eine von db und eine andere für den Webserver. Beide Container laufen auf meinem Mac OSX.

Ich kann vom Host-Computer aus auf den DB-Container zugreifen und auf die gleiche Weise vom Host-Computer aus auf den Webserver zugreifen.

Wie greife ich jedoch vom Webserver auf die Datenbankverbindung zu?

Die Art und Weise, wie ich DB Container gestartet habe, ist

docker run --name oracle-db -p 1521:1521 -p 5501:5500 oracle/database:12.1.0.2-ee

Ich habe wls container als gestartet

docker run --name oracle-wls -p 7001:7001 wls-image:latest

Ich kann auf db auf dem Host zugreifen, indem ich eine Verbindung zu herstelle

sqlplus scott/welcome1@//localhost:1521/ORCLCDB

Ich kann auf wls auf dem Host als zugreifen

http://localhost:7001/console

Also befinden sich sowohl der Webcontainer als auch der Datenbankcontainer auf dem Hostcomputer? Wenn ja, welche Docker-Version verwenden Sie? Weil ältere Versionen von Docker eine Möglichkeit hatten, während die neuen Versionen eine andere haben. Können Sie auch Docker-Compose verwenden? Das wird es einfacher machen, aber ich möchte keine Antwort mit einer Methode geben, die Sie nicht verwenden können.
Caperneoignis

Diese Antwort kann helfen, wie man von einem Container in Mac
OS

Für externe Netzwerke funktionierte diese Lösung für mich stackoverflow.com/a/38089080/1770571
Salma Gomaa

Antworten:


43

Am einfachsten ist es, --link zu verwenden. Die neueren Versionen von Docker entfernen sich jedoch davon, und tatsächlich wird dieser Schalter bald entfernt.

Der unten stehende Link bietet auch eine schöne Anleitung zum Verbinden zweier Container. Sie können den Anhangsteil überspringen, da dies nur eine nützliche Anleitung zum Hinzufügen von Elementen zu Bildern ist.

https://deis.com/blog/2016/connecting-docker-containers-1/

Der Teil, an dem Sie interessiert sind, ist die Kommunikation zwischen zwei Containern. Am einfachsten ist es, den Webserver-Container namentlich aus dem Webserver-Container zu referenzieren.

Beispiel:

Sie haben den Datenbankcontainer DB1 und den Webservercontainer WEB0 benannt. Die Container sollten sich beide im Brückennetzwerk befinden. Dies bedeutet, dass der Webcontainer unter Bezugnahme auf seinen Namen eine Verbindung zum DB-Container herstellen kann.

Wenn Sie also eine Webkonfigurationsdatei für Ihre App haben, verwenden Sie für den DB-Host den Namen DB1.

Wenn Sie eine ältere Version von Docker verwenden, sollten Sie --link verwenden.

Beispiel:

Schritt 1: docker run --name db1 oracle/database:12.1.0.2-ee

dann, wenn Sie die Web-App starten. verwenden:

Schritt 2: docker run --name web0 --link db1 webapp/webapp:3.0

und die Web-App wird mit der DB verknüpft. Wie gesagt, der --link-Schalter wird jedoch bald entfernt.

Ich würde stattdessen Docker Compose verwenden, um ein Netzwerk für Sie aufzubauen. Jedoch; Sie müssen Docker Compose für Ihr System herunterladen. https://docs.docker.com/compose/install/#prerequisites

Ein Beispiel-Setup sieht folgendermaßen aus:

Dateiname ist base.yml

version: "2"
services:
  webserver:
    image: "moodlehq/moodle-php-apache:7.1
    depends_on:
      - db
    volumes:
      - "/var/www/html:/var/www/html"
      - "/home/some_user/web/apache2_faildumps.conf:/etc/apache2/conf-enabled/apache2_faildumps.conf"
    environment:
      MOODLE_DOCKER_DBTYPE: pgsql
      MOODLE_DOCKER_DBNAME: moodle
      MOODLE_DOCKER_DBUSER: moodle
      MOODLE_DOCKER_DBPASS: "m@0dl3ing"
      HTTP_PROXY: "${HTTP_PROXY}"
      HTTPS_PROXY: "${HTTPS_PROXY}"
      NO_PROXY: "${NO_PROXY}"
  db:
    image: postgres:9
    environment:
      POSTGRES_USER: moodle
      POSTGRES_PASSWORD: "m@0dl3ing"
      POSTGRES_DB: moodle
      HTTP_PROXY: "${HTTP_PROXY}"
      HTTPS_PROXY: "${HTTPS_PROXY}"
      NO_PROXY: "${NO_PROXY}"

Dadurch wird dem Netzwerk ein generischer Name zugewiesen. Ich kann mich nicht genau erinnern, wie dieser Name lautet, es sei denn, Sie verwenden den Schalter --name.

IE docker-compose --name setup1 up base.yml

HINWEIS: Wenn Sie den Schalter --name verwenden, müssen Sie ihn verwenden, wenn Sie Docker Compose aufrufen. Auf docker-compose --name setup1 downdiese Weise können Sie mehr als eine Instanz von Webserver und DB haben. In diesem Fall weiß Docker Compose, welche Instanz Sie möchten Befehle ausführen; und so können Sie mehr als eine gleichzeitig laufen lassen. Ideal für CI / CD, wenn Sie den Test parallel auf demselben Server ausführen.

Docker Compose hat also auch die gleichen Befehle wie Docker docker-compose --name setup1 exec webserver do_some_command

Das Beste daran ist, wenn Sie DBs oder ähnliches für den Komponententest ändern möchten, können Sie dem Befehl up eine zusätzliche .yml-Datei hinzufügen, die alle Elemente mit ähnlichen Namen überschreibt. Ich halte dies für einen Schlüssel => Wertersatz .

Beispiel:

db.yml

version: "2"
services:
  webserver:
    environment:
      MOODLE_DOCKER_DBTYPE: oci
      MOODLE_DOCKER_DBNAME: XE
  db:
    image: moodlehq/moodle-db-oracle

Dann ruf an docker-compose --name setup1 up base.yml db.yml

Dadurch wird die Datenbank überschrieben. mit einem anderen Setup. Wenn Sie von jedem Container aus eine Verbindung zu diesen Diensten herstellen müssen, verwenden Sie den unter Dienst festgelegten Namen, in diesem Fall Webserver und Datenbank.

Ich denke, dies könnte in Ihrem Fall tatsächlich ein nützlicheres Setup sein. Da Sie alle benötigten Variablen in den yml-Dateien festlegen und einfach den Befehl für Docker Compose ausführen können, wenn Sie sie starten müssen. Also mehr starten und vergessen Sie das Setup.

HINWEIS: Ich habe das nicht verwendet --portBefehl, da das Offenlegen der Ports für die Container-> Containerkommunikation nicht erforderlich ist. Dies ist nur erforderlich, wenn der Host eine Verbindung zum Container oder zur Anwendung von außerhalb des Hosts herstellen soll. Wenn Sie den Port verfügbar machen, ist der Port für die gesamte Kommunikation offen, die der Host zulässt. Das Offenlegen von Web auf Port 80 entspricht dem Starten eines Webservers auf dem physischen Host und ermöglicht externe Verbindungen, sofern der Host dies zulässt. Wenn Sie aus irgendeinem Grund mehr als eine Webanwendung gleichzeitig ausführen möchten, können Sie durch das Offenlegen von Port 80 keine zusätzlichen Webanwendungen ausführen, wenn Sie versuchen, auch diesen Port verfügbar zu machen. Für CI / CD ist es daher am besten, Ports überhaupt nicht verfügbar zu machen. Wenn Sie Docker Compose mit dem Schalter --name verwenden, befinden sich alle Container in ihrem eigenen Netzwerk, damit sie nicht kollidieren. Sie werden also so ziemlich einen Container mit Containern haben.

UPDATE: Nachdem Sie weitere Funktionen verwendet und gesehen haben, wie andere dies für CICD-Programme wie Jenkins getan haben. Netzwerk ist auch eine praktikable Lösung.

Beispiel:

docker network create test_network

Mit dem obigen Befehl wird ein "test_network" erstellt, an das Sie auch andere Container anhängen können. Was mit dem --networkSchalterbediener einfach gemacht wird .

Beispiel:

docker run \
    --detach \
    --name DB1 \
    --network test_network \
    -e MYSQL_ROOT_PASSWORD="${DBPASS}" \
    -e MYSQL_DATABASE="${DBNAME}" \
    -e MYSQL_USER="${DBUSER}" \
    -e MYSQL_PASSWORD="${DBPASS}" \
    --tmpfs /var/lib/mysql:rw \
    mysql:5

Wenn Sie über Proxy-Netzwerkeinstellungen verfügen, sollten Sie diese natürlich weiterhin mit den switch-Anweisungen "-e" oder "--env-file" an die Container übergeben. So kann der Container mit dem Internet kommunizieren. Laut Docker sollten die Proxy-Einstellungen in den neueren Docker-Versionen vom Container übernommen werden. Ich gebe sie jedoch immer noch als Gewohnheit weiter. Dies ist der Ersatz für den "--link" -Schalter, der weggeht. Sobald die Container mit dem von Ihnen erstellten Netzwerk verbunden sind, können Sie mit dem 'Namen' des Containers weiterhin auf diese Container aus anderen Containern verweisen. Nach dem obigen Beispiel wäre das DB1. Sie müssen nur sicherstellen, dass alle Container mit demselben Netzwerk verbunden sind, und schon kann es losgehen.

Ein detailliertes Beispiel für die Verwendung des Netzwerks in einer Cicd-Pipeline finden Sie unter folgendem Link: https://git.in.moodle.com/integration/nightlyscripts/blob/master/runner/master/run.sh

Welches ist das Skript, das in Jenkins für einen großen Integrationstest für Moodle ausgeführt wird, aber die Idee / das Beispiel kann überall verwendet werden. Ich hoffe das hilft anderen.


Wenn der erste Link nicht funktioniert, können Sie diesen verwenden. linode.com/docs/applications/containers/…
Caperneoignis

Wie würde der Webserver beim Erstellen von Docker oder beim Ausführen eines Netzwerks auf die Datenbank verweisen? Würde es den Namen des Containers verwenden? Es sieht aus wie im zweiten Link, der der Fall ist: Wenn Sie also eine Datenbank und eine APP definieren, müsste die App in diesem Fall psql -U {USER} -h database -p 5432 {DATABASE}
verweisen

1
@Fallenreaper Wenn Sie sich im Container befinden und Docker komponiert haben, würden Sie den Namen verwenden, der unter "services:" verwendet wird, wenn Sie ihm keinen expliziten Namen geben. Im Beispiel würden Sie also "Webserver" verwenden, wenn Sie versuchen würden, eine Verbindung vom "db" -Container in der Shell herzustellen. Schauen Sie sich ein Beispiel für db.yml an, Sie würden die Namen webserver und db verwenden. Entschuldigung für die Verzögerung wurde abgelenkt und vergaß den Hinweis.
Caperneoignis

44

Es ist einfach. Wenn Sie zwei oder mehr laufende Container haben, führen Sie die folgenden Schritte aus:

docker network create myNetwork
docker network connect myNetwork web1
docker network connect myNetwork web2

Jetzt verbinden Sie sich von web1 zu web2 Container oder umgekehrt.

Verwenden Sie die internen Netzwerk-IP-Adressen, die Sie finden können, indem Sie Folgendes ausführen:

docker network inspect myNetwork

Beachten Sie, dass nur interne IP-Adressen und Ports für die über die Netzwerkbrücke verbundenen Container zugänglich sind.

Angenommen, der web1-Container wurde gestartet mit: docker run -p 80:8888 web1(was bedeutet, dass sein Server intern auf Port 8888 ausgeführt wird), und die Überprüfung myNetworkzeigt, dass die IP von web1 172.0.0.2 lautet, können Sie mithilfe von web2 eine Verbindung zu web1 herstellen curl 172.0.0.2:8888.


1
Hallo, und wie verbinde ich mich von web1 zu web2? von IP, Hostname? Woher bekomme ich diese Informationen?
Henry Ávila

Erstellen Sie in der Datei docker-compose.yml Netzwerke: myNetwork.
MxWild

11
@ HenryÁvila Sie verwenden nur den Namen des Containers (z. B. web1) als Hostnamen.
Pascal

Es ist besser, --net = host zu verwenden, wie bereits erwähnt. #hitter, es kann eine interne Verbindung über localhost: port hergestellt werden
Arch

17

Sie müssen über die IP-Adresse des Host-Computers auf db zugreifen. Wenn Sie über localhost: 1521 darauf zugreifen möchten, führen Sie den Webserver wie folgt aus:

docker run --net=host --name oracle-wls wls-image:latest

Siehe hier


1
Wie wird dies im wirklichen Leben funktionieren, wenn sich die IP des Hosts ändert, je nachdem, welche Maschinencontainer ausgeführt werden?
Vik

1
Dies gilt nur, wenn der Computer über eine statische IP- oder DNS-Adresse verfügt. Andernfalls wird der zweite Ansatz gewählt.
Xitter

Ich scheint ein Problem damit zu haben. Mein genauer Ausführungsbefehl lautet: docker run --name ora-tools-wls -it -p 7001: 7001 orawls dies funktioniert und ich kann auf meinen Server zugreifen, der auf diesem Container als localhost: 7001 / console ausgeführt wird. Der Datenbankzugriff vom Server muss jedoch erfolgen genaue IP, um einen anderen Container zu erreichen, auf dem die Datenbank ausgeführt wird. Wenn ich mit Docker-Lauf --name ora-tools-wls -it -p 7001: 7001 --network = "host" orawls gehe, kann der Server mit localhost als IP auf die Datenbank zugreifen, wie Sie erwähnt haben, aber im Browser des Host-Computers auf den Server zugreifen schlägt fehl.
Vik

3
Sie müssen nicht definieren -p 7001:7001, da alle Container den Netzwerkstapel des Hosts selbst verwenden.
Xitter

@ Vik, ich hatte das gleiche Problem und stellte fest, dass es auf dem Mac nicht unterstützt wird. Vielleicht ist es das, was du auch tust. > Der Host-Netzwerktreiber funktioniert nur auf Linux-Hosts und wird auf Docker Desktop für Mac, Docker Desktop für Windows oder Docker EE für Windows Server nicht unterstützt. docs.docker.com/network/host
Brent Fisher

7

Bei Verwendung docker-composewerden Dienste standardmäßig standardmäßig einander ausgesetzt. Docs .
Sie können auch einen Alias ​​wie angeben.

version: '2.1'
services:
  mongo:
    image: mongo:3.2.11
  redis:
    image: redis:3.2.10
  api:
    image: some-image
    depends_on:
      - mongo
      - solr
    links:
      - "mongo:mongo.openconceptlab.org"
      - "solr:solr.openconceptlab.org"
      - "some-service:some-alias"

Und dann Zugriff auf den Service angegebenen Alias als Hostnamen verwenden, zB mongo.openconceptlab.orgfür mongoin diesem Fall.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.