angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Docker - Zusammenstellen von Projekten mit identischen Dienstnamen

Verwenden Sie den Docker-Compose Servicenamen nur, wenn sich der Service nur im internen Netzwerk des Docker-Compose Projekts befindet.

25 August 2023
In Docker
post main image
https://www.pexels.com/@mikael-blomkvist

Wenn wir identische Docker-Compose Projekte mit identischen Servicenamen haben, die durch ein Docker Netzwerk verbunden sind, müssen wir sicherstellen, dass wir auf den richtigen Service zugreifen. In einem Docker -Netzwerk gibt es zwei Möglichkeiten für den Zugriff auf einen Dienst:

  • Über den Dienstnamen
  • Über den Containernamen

Ich habe mehrere Docker-Compose Projekte, die fast identisch sind, jedes Projekt befindet sich in seinem eigenen Verzeichnis und hat seine eigene Umgebung.

Ich nahm an, dass ein Service innerhalb eines Docker-Compose Projekts immer einen anderen Service innerhalb desselben Docker-Compose Projekts verwenden würde, wenn der Servicename (nicht der Containername) verwendet wird. Und dass er einen Fehler produzieren würde, wenn er nicht verfügbar wäre. Ich habe mich geirrt. Was tatsächlich passieren wird, ist, dass Sie auf den Dienst mit dem gleichen Namen in einem anderen Docker-Compose Projekt zugreifen können.

Wie immer habe ich dies auf Ubuntu 22.04 laufen lassen.

Projekt-Einrichtung

Wir haben zwei Verzeichnisse mit unseren (fast) identischen Projekten.

├── my_app1
│   ├── docker-compose.yml
│   └── .env
├── my_app2
│   ├── docker-compose.yml
│   └── .env

Die beiden 'docker-compose.yml'-Dateien sind identisch. Die '.env' Dateien sind anders, sie enthalten nur eine Umgebungsvariable, die 'COMPOSE_PROJECT_NAME'. Diese Variable wird nicht nur zur Erstellung der Containernamen verwendet, sondern auch innerhalb unserer Container, um das Projekt Docker-Compose zu identifizieren.

Wir verwenden hier die 'nicolaka/netshoot' Docker image . Es enthält viele nützliche Dienstprogramme, einschließlich eines funktionierenden 'netcat', 'nc', das wir zum Erstellen von Listener daemons verwenden.

Hier sind die Dateien:

# my_app1/.env
COMPOSE_PROJECT_NAME=my_app1

und

# my_app2/.env
COMPOSE_PROJECT_NAME=my_app2

und

# docker-compose.yml

version: '3.7' 

x-service_defaults: &service_defaults
  env_file:
    - ./.env
  restart: always

services:
  app:
    << : *service_defaults
    image: nicolaka/netshoot
    command: bash -c "echo \"From ${COMPOSE_PROJECT_NAME} - app:\" | /usr/bin/nc -l 80"
    
    networks: 
      - internal_network
      - app_network

  web:
    << : *service_defaults
    image: nicolaka/netshoot
    command: bash -c "echo \"From ${COMPOSE_PROJECT_NAME} - web:\" | /usr/bin/nc -l 81"

    networks: 
      - internal_network
      - app_network

networks:
  internal_network:
  app_network:
    external:
      name: my_app_network

Bevor wir beginnen, erstellen wir das externe Docker -Netzwerk:

docker network create my_app_network

Durchführung einiger Prüfungen

Öffnen Sie einige Terminals und starten Sie beide Projekte, indem Sie diesen Befehl in jedem Verzeichnis ausführen:

docker-compose up

Überprüfen Sie, ob die folgenden Container erstellt wurden und ausgeführt werden:

my_app1_app_1
my_app1_web_1
my_app2_app_1
my_app2_web_1

Führen Sie nun in einem anderen Terminal aus:

docker run -it --network=my_app_network --rm busybox

Greifen Sie auf einen Dienst in unseren Containern zu, indem Sie den Containernamen verwenden:

telnet my_app_1_app_1 80

Die Antwort wird sein:

Connected to my_app1_app_1
From my_app1 - app:

Dies funktioniert wie erwartet. Geben Sie etwas Text ein. Dieser wird als Echo ausgegeben. Sie können dies auch im Terminal des Projekts 'my_app1' Docker-Compose überprüfen.

Generierung des Fehlers

Zunächst betreten wir den 'app' -Dienst des 'my_app1' -Projekts:

docker exec -it my_app1_app_1 bash

Nun greifen wir auf den Dienst 'web' im gleichen Projekt Docker-Compose zu, indem wir den Dienstnamen verwenden:

telnet web 81

Die Antwort lautet:

Connected to web
From my_app1 - web:

Perfekt, das ist das, was wir erwartet haben.

Lassen Sie uns nun den Dienst 'web' im Projekt 'my_app1' (vorübergehend) verschwinden. Dazu nehmen wir ihn herunter.

In einem anderen Terminal wechseln wir in das Verzeichnis 'my_app1' und geben ein:

docker-compose stop web

Jetzt greifen wir wieder auf den Dienst 'web' im selben Projekt zu:

telnet web 81

Die Antwort lautet:

Connected to web
From my_app2 - web:

Oh, oh. Jetzt greifen wir auf den Dienst 'web' in 'my_app2' zu, während wir auf den Dienst 'web' in 'my_app1' zugreifen wollten. Beachten Sie, dass es (viel) bessere, aber auch viel komplexere Möglichkeiten gibt, dies zu simulieren.

Lösungen

Hier gibt es zwei mögliche Lösungen, je nach Situation:

Lösung 1. Wenn der Dienst 'web' nicht extern sein muss, entfernen wir ihn aus dem externen Netz

Wir tun dies für beide Projekte (denken Sie daran, dass die Dateien "docker-compose.yml" identisch sind):

  web:
    << : *service_defaults
    image: nicolaka/netshoot
    command: bash -c "echo \"From ${COMPOSE_PROJECT_NAME} - web:\" | /usr/bin/nc -l 81"

    networks: 
      - internal_network
      #- app_network

Fahren Sie die Container herunter und wieder hoch und stoppen Sie den Dienst 'web' des Projekts 'my_app1' wieder.

Wenn Sie nun versuchen, auf den Dienst 'web' zuzugreifen, siehe oben:

telnet web 81

Die Antwort wird nach einiger Zeit lauten:

telnet: bad address 'web'

Gut. Wir erhalten eine Fehlermeldung, wenn der Dienst nicht verfügbar ist.

Lösung 2. Wenn der 'web' -Dienst auch extern sein muss, verwenden wir immer den Containernamen des 'web' -Dienstes, wenn wir uns auf ihn beziehen, auch wenn wir uns im selben Docker-Compose-Projekt befinden.

Das ist nicht wirklich eine schöne Lösung, aber es gibt keine andere Möglichkeit. Wenn der 'app' -Dienst auf den 'web' -Dienst im selben Docker-Compose-Projekt zugreifen möchte, können wir den Containernamen mit Hilfe der Variable 'COMPOSE_PROJECT_NAME' konstruieren:

container_name = <COMPOSE_PROJECT_NAME>_<service name>_1

Für den Dienst 'web' in 'my_app1':

web_container_name = my_app1_web_1

Zusammenfassung

Ich bin auf dieses Problem gestoßen, als ich von einem Container auf zwei Container umstieg. Seltsame Dinge begannen zu passieren, und Daten wurden zwischen den Containern vermischt. Nachdem ich das Problem gefunden hatte, simulierte ich es mit dem obigen Code. Dann habe ich es für mein Projekt behoben. Lektion gelernt: Niemals etwas annehmen.

Links / Impressum

Docker - Change pre-defined environment variables in Docker Compose
https://docs.docker.com/compose/environment-variables/envvars

nicolaka / netshoot
https://github.com/nicolaka/netshoot

Einen Kommentar hinterlassen

Kommentieren Sie anonym oder melden Sie sich zum Kommentieren an.

Kommentare

Eine Antwort hinterlassen

Antworten Sie anonym oder melden Sie sich an, um zu antworten.