Kommunikation zwischen mehreren Docker-Compose-Projekten

253

Ich habe zwei separate docker-compose.ymlDateien in zwei verschiedenen Ordnern:

  • ~/front/docker-compose.yml
  • ~/api/docker-compose.yml

Wie kann ich sicherstellen, dass ein Container in frontAnforderungen an einen Container in senden kann api?

Ich weiß, dass die --default-gatewayOption docker runfür einen einzelnen Container festgelegt werden kann, sodass diesem Container eine bestimmte IP-Adresse zugewiesen werden kann, aber es scheint, dass diese Option bei Verwendung nicht verfügbar ist docker-compose.

Momentan mache ich ein docker inspect my_api_container_idund schaue mir das Gateway in der Ausgabe an. Es funktioniert, aber das Problem ist, dass diese IP zufällig zugewiesen wird, sodass ich mich nicht darauf verlassen kann.

Eine andere Form dieser Frage könnte daher sein:

  • Kann ich mit Docker-Compose einem bestimmten Container eine feste IP-Adresse zuweisen?

Aber am Ende kümmere ich mich um:

  • Wie können zwei verschiedene Docker-Compose-Projekte miteinander kommunizieren?
Jivan
quelle
4
Ich habe mich heute noch einmal darum gekümmert. Die Entwickler haben endlich nachgegeben und willkürliche Netzwerknamen zugelassen. Mit der Compose-Datei Version 3.5 können Sie unter dem Schlüssel 'Netzwerke' einen Namen für das Standardnetzwerk angeben. Dadurch wird ein benanntes Netzwerk ohne das übliche Projektnamenpräfix erstellt, falls es nicht vorhanden ist.
cstrutton

Antworten:

325

Sie müssen nur sicherstellen, dass sich die Container, mit denen Sie miteinander kommunizieren möchten, im selben Netzwerk befinden. Netzwerke sind ein erstklassiges Docker-Konstrukt und nicht spezifisch für die Erstellung.

# front/docker-compose.yml
version: '2'
services:
  front:
    ...
    networks:
      - some-net
networks:
  some-net:
    driver: bridge

...

# api/docker-compose.yml
version: '2'
services:
  api:
    ...
    networks:
      - front_some-net
networks:
  front_some-net:
    external: true

Hinweis: Das Netzwerk Ihrer App erhält einen Namen basierend auf dem „Projektnamen“, der auf dem Namen des Verzeichnisses basiert, in dem es sich befindet. In diesem Fall wurde ein Präfix front_hinzugefügt

Sie können dann unter Verwendung des Dienstnamens miteinander sprechen. Von frontdir aus kannst du ping apiund umgekehrt.

johnharris85
quelle
1
Jivan, das ist keine Lösung. Ihre Container sollten nichts über den Host wissen oder so manipuliert werden müssen. Meine Antwort war allerdings ziemlich kurz, ich habe sie detaillierter aktualisiert.
Johnharris85
3
Robert Moskal nur, wenn Sie herumhacken, um die IP Ihres Docker-Hosts in die Container zu bekommen. Besser, sie kommunizieren in einem gemeinsamen Docker-definierten Netzwerk.
Johnharris85
2
Bitte beachten Sie, dass das Präfix "front_" für das Netzwerk automatisch aus dem Ordner erstellt wird, in dem es ausgeführt wird. Wenn sich Ihre erste Docker-Compose-Datei in "example / docker-compose.yml" befindet, wird sie stattdessen "example_default" genannt.
AngryUbuntuNerd
7
Sie können einem Netzwerk auch mithilfe der nameEigenschaft einen Namen geben , wodurch das automatische Voranstellen des Projektnamens deaktiviert wird. Dann kann jedes Projekt dieses Netzwerk verwenden und es automatisch erstellen, wenn es noch nicht vorhanden ist.
SteveB
2
@SteveB - Beachten Sie, dass die Eigenschaft name nur ab Docker-Compose-Dateien ab Version 3.5
funktioniert
78

Nur eine kleine Ergänzung zu @ johnharris85s großartiger Antwort: Wenn Sie eine Docker-Compose-Datei ausführen, wird ein " default" Netzwerk erstellt, das Sie einfach als externes Netzwerk zur anderen Compose-Datei hinzufügen können:

# front/docker-compose.yml 
version: '2' 
  services:   
    front_service:
    ...

...

# api/docker-compose.yml
version: '2'
services:
  api_service:
    ...
    networks:
      - front_default
networks:
  front_default:
    external: true

Für mich war dieser Ansatz besser geeignet, da ich nicht die erste Docker-Compose-Datei besaß und mit ihr kommunizieren wollte.

Tal Joffe
quelle
Gehen Sie einfach auf die richtige Weise, um diesem externen Netzwerk statische IP-Adressen zuzuweisen. Ich habe es innerhalb des services:Tags gemanagt, die Sintax wurde networks:dann verschachtelt front_default:(entfernen Sie das "-") und dann verschachteln wir eine statische IP:ipv4_address: '172.20.0.44'
Junior Mayhé
76

UPDATE: Ab Compose File Version 3.5:

Das funktioniert jetzt:

version: "3.5"
services:
  proxy:
    image: hello-world
    ports:
      - "80:80"
    networks:
      - proxynet

networks:
  proxynet:
    name: custom_network

docker-compose up -dtritt einem Netzwerk mit dem Namen 'custom_network' bei. Wenn es nicht existiert, wird es erstellt!

root@ubuntu-s-1vcpu-1gb-tor1-01:~# docker-compose up -d
Creating network "custom_network" with the default driver
Creating root_proxy_1 ... done

Jetzt können Sie dies tun:

version: "2"
services:
  web:
    image: hello-world
    networks:
      - my-proxy-net
networks:
  my-proxy-net:
    external:
      name: custom_network

Dadurch wird ein Container erstellt, der sich im externen Netzwerk befindet.

Ich kann noch keine Referenz in den Dokumenten finden, aber es funktioniert!

cstrutton
quelle
Müssen Sie die beiden Dienste in einer bestimmten Reihenfolge starten? Können Sie eines davon starten und das erste wird das Netzwerk erstellen und das zweite wird dem Netzwerk beitreten?
Slashdottir
4
Der erste Dienst (Proxy oben) erstellt das Netzwerk. Die Syntax im zweiten Beispiel ergänzt sie.
Cstrutton
2
@slashdottir Sie können das Netzwerk im zweiten Dienst nicht als extern markieren und es wird erstellt, wenn es noch nicht vorhanden ist.
SteveB
2
Es funktioniert. Ich habe gerade ein DO-Tröpfchen mit der neuesten Docker-Komposition gedreht. Ich habe das Beispiel zu einem tatsächlichen Arbeitsbeispiel bearbeitet.
Cstrutton
1
In meinem Fall stellte sich heraus, dass dies eine geeignetere Lösung war als die akzeptierte Antwort. Das Problem mit dem externen Netzwerk bestand darin, dass Container in vordefinierter Reihenfolge gestartet werden mussten. Für meinen Kunden war dies nicht akzeptabel. Ein benanntes Netzwerk (seit 3.5) erwies sich als perfekte Lösung. Vielen Dank.
ygor
24

Alle Container von apikönnen mit der folgenden Konfiguration dem front Standardnetzwerk beitreten :

# api/docker-compose.yml

...

networks:
  default:
    external:
      name: front_default

Siehe Docker-Erstellungshandbuch: Verwenden eines bereits vorhandenen Netzwerks (siehe unten)

dedek
quelle
12

Die vorherigen Beitragsinformationen sind korrekt, enthalten jedoch keine Details zum Verknüpfen von Containern, die als "external_links" verbunden werden sollten.

Hoffe, dieses Beispiel macht Ihnen klarer:

  • Angenommen, Sie haben app1 / docker-compose.yml mit zwei Diensten (svc11 und svc12) und app2 / docker-compose.yml mit zwei weiteren Diensten (svc21 und svc22) und müssen eine gekreuzte Verbindung herstellen:

  • svc11 muss eine Verbindung zum Container von svc22 herstellen

  • svc21 muss eine Verbindung zum Container von svc11 herstellen.

Die Konfiguration sollte also folgendermaßen aussehen:

Dies ist app1 / docker-compose.yml:


version: '2'
services:
    svc11:
        container_name: container11
        [..]
        networks:
            - default # this network
            - app2_default # external network
        external_links:
            - container22:container22
        [..]
    svc12:
       container_name: container12
       [..]

networks:
    default: # this network (app1)
        driver: bridge
    app2_default: # external network (app2)
        external: true

Dies ist app2 / docker-compose.yml:


version: '2'
services:
    svc21:
        container_name: container21
        [..]
        networks:
            - default # this network (app2)
            - app1_default # external network (app1)
        external_links:
            - container11:container11
        [..]
    svc22:
       container_name: container22
       [..]

networks:
    default: # this network (app2)
        driver: bridge
    app1_default: # external network (app1)
        external: true
Daniel Blanco
quelle
6

Seit Compose 1.18 (Spezifikation 3.5) können Sie das Standardnetzwerk einfach mit Ihrem eigenen Namen für alle benötigten Compose YAML-Dateien überschreiben. Es ist so einfach, wie Folgendes an sie anzuhängen:

networks:
  default:
    name: my-app

Die oben vorausgesetzt , dass Sie versionauf 3.5(oder höher , wenn sie deprecate es nicht in 4+).

Andere Antworten haben dasselbe gezeigt; Dies ist eine vereinfachte Zusammenfassung.

Emyller
quelle
2

Ich würde sicherstellen, dass alle Container docker-composezum selben Netzwerk gehören, indem ich sie zur gleichen Zeit zusammensetze, indem ich Folgendes verwende:

docker compose --file ~/front/docker-compose.yml --file ~/api/docker-compose.yml up -d
Nauraushaun
quelle
Erlaubt mir das zum Beispiel, einen linkoder depends_onvon einem Container vorne zu einem Container api zu machen?
Jivan
tatsächlich, wenn ich tue, was Sie vorschlagen, Docker-Compose-Antworten entweder build path ~/front/api either does not exist or is not accessibleoder umgekehrt,build path ~/api/front either does not exist or is not accessible
Jivan
1
Wenn Sie sie gleichzeitig komponieren, sollten Sie das nicht müssen. Es wird ein Netzwerk mit all Ihren Containern erstellt, die alle über den Dienstnamen aus der Erstellungsdatei ( nicht über den Containernamen) kommunizieren können .
Nauraushaun
Es ist möglicherweise einfacher, wenn sich die beiden Erstellungsdateien im selben Ordner befinden. Aber ich denke nicht, dass das notwendig ist - ich denke, es sollte so oder so funktionieren.
Nauraushaun
2
Diese Lösung funktioniert nicht, siehe meinen Kommentar zu diesem Thread: github.com/docker/compose/issues/3530#issuecomment-222490501
johnharris85
2

UPDATE: Ab Compose File Version 3.5:

Ich bin auf ein ähnliches Problem gestoßen und habe es gelöst, indem ich eine kleine Änderung in einem meiner docker-compose.yml-Projekte hinzugefügt habe.

Zum Beispiel haben wir zwei APIs scoringund ner. ScoringDie API muss eine Anfrage an die nerAPI senden, um die Eingabeanforderung zu verarbeiten. Zu diesem Zweck müssen beide dasselbe Netzwerk gemeinsam nutzen.

Hinweis: Jeder Container verfügt über ein eigenes Netzwerk, das zum Zeitpunkt der Ausführung der App im Docker automatisch erstellt wird. Zum Beispiel wird ner API-Netzwerk wie erstellt ner_defaultund das Scoring-API-Netzwerk wird als benannt scoring default. Diese Lösung funktioniert für Version: '3'.

Wie im obigen Szenario möchte meine Scoring-API mit ner API kommunizieren, dann füge ich die folgenden Zeilen hinzu. Das heißt, wenn ich den Container für ner api erstelle, wird er automatisch zum Scoring_Default-Netzwerk hinzugefügt.

networks:
  default:
      external:
        name: scoring_default

ner / docker-compose.yml

version: '3'
services:
  ner:
    build: .
    ...

networks:
  default:
      external:
        name: scoring_default

Scoring / Docker-Compose.yml

version: '3'
services:
  api:
    build: .
    ...

Wir können sehen, wie die oben genannten Container jetzt Teil desselben Netzwerks sind, das scoring_defaultmit dem folgenden Befehl aufgerufen wird:

Docker inspizieren Scoring_Default

{
    "Name": "scoring_default",
        ....
    "Containers": {
    "14a6...28bf": {
        "Name": "ner_api",
        "EndpointID": "83b7...d6291",
        "MacAddress": "0....",
        "IPv4Address": "0.0....",
        "IPv6Address": ""
    },
    "7b32...90d1": {
        "Name": "scoring_api",
        "EndpointID": "311...280d",
        "MacAddress": "0.....3",
        "IPv4Address": "1...0",
        "IPv6Address": ""
    },
    ...
}
Nomiluks
quelle
1

Sie können .envallen Ihren Projekten eine Datei hinzufügen, die Folgendes enthält COMPOSE_PROJECT_NAME=somename.

COMPOSE_PROJECT_NAME überschreibt das Präfix, das zum Benennen von Ressourcen verwendet wird. Daher werden alle Ihre Projekte somename_defaultals Netzwerk verwendet, sodass Dienste wie im selben Projekt miteinander kommunizieren können.

NB: Sie erhalten Warnungen für "verwaiste" Container, die aus anderen Projekten erstellt wurden.

Exagone313
quelle
0
version: '2'
services:
  bot:
    build: .
    volumes:
      - '.:/home/node'
      - /home/node/node_modules
    networks:
      - my-rede
    mem_limit: 100m
    memswap_limit: 100m
    cpu_quota: 25000
    container_name: 236948199393329152_585042339404185600_bot
    command: node index.js
    environment:
      NODE_ENV: production
networks:
  my-rede:
    external:
      name: name_rede_externa
Pedro
quelle
0

Um ein anderes Docker-Compose-Netzwerk zu verwenden, gehen Sie einfach wie folgt vor (um Netzwerke zwischen Docker-Compose zu teilen):

  1. Führen Sie das erste Docker-Compose-Projekt von aus up -d
  2. Suchen Sie den Netzwerknamen des ersten Docker-Compose nach: docker network ls(Er enthält den Namen des Stammverzeichnisprojekts.)
  3. Verwenden Sie dann diesen Namen von dieser Struktur unten in der zweiten Docker-Compose-Datei.

zweite docker-compose.yml

version: '3'
services:
  service-on-second-compose:  # Define any names that you want.
    .
    .
    .
    networks:
      - <put it here(the network name that comes from "docker network ls")>

networks:
  - <put it here(the network name that comes from "docker network ls")>:
    external: true
Ali Hallaji
quelle
0

Eine andere Option besteht darin, das erste Modul mit dem 'Docker-Compose' hochzufahren, die mit dem Modul verbundene IP zu überprüfen und das zweite Modul wie extern mit dem vorherigen Netz zu verbinden und auf die interne IP zu zeigen

Beispiel App1 - Neues Netzwerk in den Servicezeilen erstellt, unten als extern: true markieren app2 - Das von App1 beim Hochfahren erstellte "neue Netzwerk" angeben, unten als extern: true markieren und in der Konfiguration festlegen Zum Verbinden die IP, die App1 in diesem Netz hat.

Damit sollten Sie in der Lage sein, miteinander zu sprechen

* Dieser Weg ist nur für den Fokus auf lokale Tests gedacht, um keine überkomplexe Konfiguration vorzunehmen. ** Ich weiß, dass dies ein sehr 'Patch-Weg' ist, aber für mich funktioniert und ich denke, dass es so einfach ist, dass andere dies nutzen können

Leonardo Rey
quelle
0

Wenn du bist

  • Versuchen Sie, zwischen zwei Containern aus verschiedenen Docker-Compose-Projekten zu kommunizieren , und möchten Sie nicht dasselbe Netzwerk verwenden (weil sie beispielsweise PostgreSQL- oder Redis-Container am selben Port haben und Sie es vorziehen, diese Ports nicht zu ändern und nicht zu verwenden im selben Netzwerk)
  • Entwicklung vor Ort und wollen die Kommunikation zwischen zwei Docker-Compose-Projekten imitieren
  • Ausführen von zwei Docker-Compose-Projekten auf localhost
  • Entwickeln Sie insbesondere Django-Apps oder die Django Rest Framework (drf) -API und führen Sie die App in einem Container auf einem exponierten Port aus
  • immer Connection refusedbeim Versuch, zwischen zwei Containern zu kommunizieren

Und du willst

  • Container api_akommunizieren mit api_b(oder umgekehrt) ohne dasselbe "Docker-Netzwerk"

(Beispiel unten)

Sie können "Host" des zweiten Containers als IP Ihres Computers und Ports verwenden, der im Docker-Container zugeordnet ist. Sie können die IP Ihres Computers mit diesem Skript abrufen (von: Suchen lokaler IP-Adressen mit Pythons stdlib ):

import socket
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

Beispiel:

project_api_a/docker-compose.yml::

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_a
    image: api_a:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

Im api_aContainer wird die Django-App ausgeführt: manage.py runserver 0.0.0.0:8000

und zweite docker-compose.yml aus einem anderen Projekt:

project_api_b/docker-compose-yml ::

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_b
    image: api_b:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

Im api_bContainer wird die Django-App ausgeführt: manage.py runserver 0.0.0.0:8001

Und versucht , aus dem Behälter zu verbinden , api_aum api_bdann URL api_bwird ein Container sein: http://<get_ip_from_script_above>:8001/

Dies kann besonders nützlich sein, wenn Sie mehr als zwei (drei oder mehr) Docker-Compose-Projekte verwenden und es schwierig ist, ein gemeinsames Netzwerk für alle Projekte bereitzustellen - es ist eine gute Problemumgehung und Lösung

Rafał
quelle