[Docker] Связь между контейнерами через хост-порт без общего сетевого соединения (host.docker.internal)



Теги: Docker, DevOps, Сеть, host.docker.internal

1. Проблема

В разработческой среде часто управляют несколькими сервисами с помощью Docker.

  • App-A (например, DRF) находится в network-A.

  • App-B (например, Nextcloud) находится в network-B.

  • Оба контейнера запускаются на одной и той же хост-машине.

  • App-B привязан к 8080 порту на хосте. (например, docker run -p 8080:80 ...)

App-A должен вызвать App-B через API. Я не хочу связывать две сети через мост. Разве нельзя просто вызвать хост-порт 8080?

Если вызвать localhost:8080 или 127.0.0.1:8080 из контейнера, то это будет ссылаться не на хост-машину, а на сам контейнер.

2. Решение: host.docker.internal

Самое простое решение — использовать специальное DNS-имя host.docker.internal.

host.docker.internal: специальное имя хоста, которое интерпретируется как IP-адрес хост-машины внутри контейнера.

В коде App-A (DRF), когда вызывается Nextcloud, задайте URL следующим образом.

# Внутренний код DRF (App-A)
import requests

# Используйте 'host.docker.internal' вместо 'localhost'.
NEXTCLOUD_URL = "http://host.docker.internal:8080"

try:
    response = requests.get(NEXTCLOUD_URL)
    print(f"Успешное подключение к Nextcloud: {response.status_code}")
except requests.exceptions.ConnectionError:
    print("Ошибка подключения к Nextcloud")

То же самое применимо и для тестирования с помощью curl внутри контейнера.

# Выполнение внутри контейнера App-A
curl http://host.docker.internal:8080

3. ⚠️ Важно: Настройка окружения Linux

Пользователи Docker Desktop (macOS, Windows) могут использовать host.docker.internal по умолчанию.

Однако для Linux-хостов нужно добавить эту настройку вручную. Вы можете использовать специальное ключевое слово host-gateway для сопоставления IP хоста.

Способ 1: Использование docker run

Добавьте флаг --add-host.

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

Способ 2: Использование docker-compose.yml

Добавьте extra_hosts к сервису App-A (DRF).

services:
  drf-app:
    image: my-drf-app-image
    networks:
      - network-A
    extra_hosts:
      # Сопоставление host.docker.internal с IP хоста (host-gateway)
      - "host.docker.internal:host-gateway"

# ... (определение network-A) ...

4. Итоги

При взаимодействии между изолированными сетями Docker нет необходимости усложнять связь сетей.

  1. Привяжите целевой контейнер (Nextcloud) к хост-порту (8080).

  2. Сделайте запрос из контейнера (DRF) по адресу http://host.docker.internal:8080.

  3. Если хост на Linux, не забудьте добавить настройку extra_hosts (host.docker.internal:host-gateway) в вызывающий контейнер.