[Docker] Kommunikation zwischen Containern über Host-Port ohne Netzwerkfreigabe (host.docker.internal)



Tags: Docker, DevOps, Network, host.docker.internal

1. Problematik

In der Entwicklungsumgebung verwalten wir häufig mehrere Dienste über Docker.

  • App-A (z. B. DRF) befindet sich im network-A.

  • App-B (z. B. Nextcloud) befindet sich im network-B.

  • Beide Container laufen auf demselben Host-System.

  • App-B ist mit dem 8080 Port des Hosts verbunden. (z. B. docker run -p 8080:80 ...)

App-A muss App-B über die API aufrufen. Ich möchte nicht umständlich die beiden Netzwerke mit einem Bridge verbinden. Können wir nicht einfach den Host-Port 8080 aufrufen?

Wenn ich in einem Container localhost:8080 oder 127.0.0.1:8080 anrufe, verweist das auf den Container selbst, nicht auf das Host-System.

2. Lösung: host.docker.internal

Die einfachste Lösung ist die Verwendung des speziellen DNS-Namens host.docker.internal.

host.docker.internal: Ein spezieller Hostname, der innerhalb des Containers als IP-Adresse des Host-Systems interpretiert wird.

Wenn ich aus dem Code von App-A (DRF) Nextcloud aufrufe, setze ich die URL wie folgt:

# interner Code von DRF (App-A)
import requests

# Verwenden Sie 'host.docker.internal' anstelle von 'localhost'.
NEXTCLOUD_URL = "http://host.docker.internal:8080"

try:
    response = requests.get(NEXTCLOUD_URL)
    print(f"Nextcloud Verbindung erfolgreich: {response.status_code}")
except requests.exceptions.ConnectionError:
    print("Nextcloud Verbindung fehlgeschlagen")

Das gleiche gilt, wenn ich innerhalb des Containers mit curl teste.

# Ausgeführt innerhalb des App-A-Containers
curl http://host.docker.internal:8080

3. ⚠️ Wichtig: Einstellungen für Linux-Hosts

Benutzer von Docker Desktop (macOS, Windows) haben host.docker.internal standardmäßig aktiviert.

In einer Linux-Host-Umgebung muss diese Einstellung jedoch manuell hinzugefügt werden. Das spezielle Schlüsselwort host-gateway kann verwendet werden, um die Host-IP zuzuordnen.

Methode 1: Bei der Verwendung von docker run

Fügen Sie das Flag --add-host hinzu.

docker run \
  --add-host=host.docker.internal:host-gateway \
  --network network-A \
  my-drf-app-image

Methode 2: Bei der Verwendung von docker-compose.yml

Fügen Sie extra_hosts zum App-A (DRF)-Dienst hinzu.

services:
  drf-app:
    image: my-drf-app-image
    networks:
      - network-A
    extra_hosts:
      # Zuordnung von host.docker.internal zur Host-IP (host-gateway)
      - "host.docker.internal:host-gateway"

# ... (Definition von network-A) ...

4. Zusammenfassung

Bei der Kommunikation zwischen getrennten Docker-Netzwerken müssen Sie kein komplexes Netzwerk erstellen.

  1. Verbinden Sie den Ziel-Container (Nextcloud) mit dem Host-Port (8080).

  2. Der aufrufende Container (DRF) sendet die Anfrage an http://host.docker.internal:8080.

  3. Wenn der Host ein Linux ist, denken Sie daran, im aufrufenden Container extra_hosts (host.docker.internal:host-gateway) einzufügen.