[Docker] Comunicar contenedores a través de puertos del host sin compartir red (host.docker.internal)
Etiquetas: Docker, DevOps, Red, host.docker.internal
1. Situación del problema
Es común gestionar múltiples servicios en el entorno de desarrollo utilizando Docker.
-
App-A(por ejemplo: DRF) está ennetwork-A. -
App-B(por ejemplo: Nextcloud) está ennetwork-B. -
Ambos contenedores se ejecutan en la misma máquina anfitriona.
-
App-Bestá vinculado al puerto8080del host. (por ejemplo:docker run -p 8080:80 ...)
Necesitamos hacer una llamada API desde App-A a App-B. No queremos complicarnos conectando las dos redes a través de un puente. ¿No podemos llamar directamente al puerto 8080 del host?
Al llamar a localhost:8080 o 127.0.0.1:8080 desde dentro del contenedor, se refiere a sí mismo y no a la máquina anfitriona.
2. Solución: host.docker.internal
La solución más sencilla es usar un nombre DNS especial llamado host.docker.internal.
host.docker.internal: un nombre de host especial que se resuelve a la dirección IP de la máquina anfitriona desde dentro del contenedor.
En el código de App-A (DRF) al hacer la llamada a Nextcloud, configuramos la URL de la siguiente manera.
# Código interno de DRF (App-A)
import requests
# Utilizamos 'host.docker.internal' en vez de 'localhost'.
NEXTCLOUD_URL = "http://host.docker.internal:8080"
try:
response = requests.get(NEXTCLOUD_URL)
print(f"Conexión a Nextcloud exitosa: {response.status_code}")
except requests.exceptions.ConnectionError:
print("Fallo en la conexión a Nextcloud")
Lo mismo ocurre al probar desde dentro del contenedor con curl.
# Ejecutar desde dentro del contenedor de App-A
curl http://host.docker.internal:8080
3. ⚠️ Importante: Configuración del entorno de host de Linux
Los usuarios de Docker Desktop (macOS, Windows) tienen host.docker.internal funcionando por defecto.
Sin embargo, en un entorno de host Linux, esta configuración debe añadirse manualmente. Se puede mapear la IP del host usando una palabra clave especial llamada host-gateway.
Método 1: Al usar docker run
Agregue el flag --add-host.
docker run \
--add-host=host.docker.internal:host-gateway \
--network network-A \
my-drf-app-image
Método 2: Al usar docker-compose.yml
Agregue extra_hosts al servicio de App-A (DRF).
services:
drf-app:
image: my-drf-app-image
networks:
- network-A
extra_hosts:
# Mapee host.docker.internal a la IP de la máquina host (host-gateway)
- "host.docker.internal:host-gateway"
# ... (definición de network-A) ...
4. Resumen
No es necesario complicar las conexiones de red al comunicar entre redes separadas en Docker.
-
Vincule el contenedor objetivo (Nextcloud) al puerto del host (
8080). -
Haga una solicitud desde el contenedor emisor (DRF) a la dirección
http://host.docker.internal:8080. -
Si el host es Linux, no olvide añadir la configuración de
extra_hosts(host.docker.internal:host-gateway) en el contenedor emisor.
No hay comentarios.