# Redes en Compose


Compose gestiona la red por ti de forma predeterminada, pero te ofrece un control detallado cuando lo necesitas. Esta página explica cómo funciona la red por defecto y cómo los contenedores se descubren entre sí por su nombre. También cubre cuándo y cómo definir redes personalizadas, conectar servicios en proyectos de Compose independientes, mapear nombres de host personalizados y depurar problemas de conectividad.

## Red por defecto y descubrimiento de servicios

Por defecto, Compose configura una única [red](/reference/cli/docker/network/create/) para tu aplicación. Cada contenedor de un servicio se une a la red por defecto y es tanto accesible por otros contenedores en esa red como detectable por su nombre de servicio. Esta red utiliza el controlador `bridge`. Para comprender cuándo utilizarías un controlador diferente, consulta [Controladores de red: bridge frente a host](#change-the-network-mode).

Para la mayoría de las configuraciones de desarrollo, la red por defecto es suficiente. Al ejecutar `docker compose up`, Compose crea una red llamada `<project-name>_default` y conecta todos los servicios a ella. Cada servicio registra su nombre con un servidor DNS interno, de modo que los contenedores pueden comunicarse entre sí utilizando el nombre del servicio directamente. No se necesitan direcciones IP ni configuración manual.

Por ejemplo, supón que tu aplicación está en un directorio llamado `myapp` y tu archivo `compose.yaml` se ve así:

```yaml
services:
  web:
    build: .
    ports:
      - "8000:8000"
  db:
    image: postgres:latest
    ports:
      - "8001:5432"
```

Compose conecta automáticamente todos los servicios a la red por defecto, por lo que no es necesario definir `networks` de forma explícita en el archivo de Compose.

Al ejecutar `docker compose up`, sucede lo siguiente:

1. Se crea una red llamada `myapp_default`.
2. Se crea un contenedor utilizando la configuración de `web`. Se une a `myapp_default` bajo el nombre `web`.
3. Se crea un contenedor utilizando la configuración de `db`. Se une a `myapp_default` bajo el nombre `db`.

Ahora, cada contenedor puede buscar el nombre de servicio `web` o `db` y obtener la dirección IP del contenedor correspondiente. El servicio `web` puede conectarse a la base de datos en `postgres://db:5432`. Desde la máquina host, se puede acceder a la misma base de datos en `postgres://localhost:8001` si tu contenedor se ejecuta localmente.

> [!TIP]
>
> Docker asigna direcciones IP de contenedores de forma dinámica desde la subred de la red cada vez que se inicia un contenedor, por lo que no se persisten tras reinicios o recreaciones. Esto significa que siempre debes hacer referencia a los servicios por su nombre, no por la dirección IP. Cuando se recrean los contenedores, por ejemplo tras un cambio de configuración, reciben una nueva dirección IP. El nombre del servicio permanece estable.

A la red de tu aplicación se le asigna un nombre basado en el "nombre del proyecto", el cual se toma del nombre del directorio en el que reside. Puedes sobrescribir el nombre del proyecto con la [bandera `--project-name`](/reference/cli/docker/compose/) o con la [variable de entorno `COMPOSE_PROJECT_NAME`](/compose/how-tos/networking/environment-variables/envvars/#compose_project_name).

El `HOST_PORT` y el `CONTAINER_PORT` sirven para propósitos diferentes. En el ejemplo anterior, para `db`, el `HOST_PORT` es `8001` y el puerto del contenedor es `5432` (el valor por defecto de Postgres). La comunicación entre servicios en red utiliza el `CONTAINER_PORT`. El puerto del host solo se utiliza cuando se accede al servicio desde fuera de la red.

### Actualización de contenedores en la red

Si realizas un cambio de configuración en un servicio y ejecutas `docker compose up` para actualizarlo, el contenedor antiguo se elimina y el nuevo se une a la red bajo una dirección IP diferente pero con el mismo nombre. Los contenedores en ejecución pueden buscar ese nombre y conectarse a la nueva dirección, pero la dirección antigua deja de funcionar.

Si algún contenedor tiene conexiones abiertas con el contenedor antiguo, estas se cierran. Es responsabilidad de cada contenedor detectar esta condición, volver a buscar el nombre y reconectarse.

## Cambiar el modo de red

Por defecto, cada servicio se une a la red bridge del proyecto. Es el modo de red más seguro. Si no especificas [`network_mode`](/reference/compose-file/services/#network_mode), este es el tipo de red que estás creando.

Puedes sobrescribir el modo de red por servicio. La opción `network_mode` admite los siguientes valores:

- `host`: El contenedor comparte la pila de red del host. No se necesita ni se admite el mapeo de puertos, y la resolución DNS por nombre de servicio no funciona. Úsalo para herramientas a nivel de sistema, como monitores de red, que requieren acceso directo a las interfaces del host. Un contenedor que utiliza `network_mode: host` puede acceder a todos los puertos del host y observar todo el tráfico de red en él. Úsalo únicamente cuando sea realmente necesario.
- `none`: Desactiva toda la red del contenedor.
- `service:{name}`: Otorga al contenedor acceso al contenedor especificado haciendo referencia a su nombre de servicio.
- `container:{name}`: Otorga al contenedor acceso al contenedor especificado haciendo referencia a su ID de contenedor.

Puedes mezclar modos en un solo proyecto:

```yaml
services:
  app:
    image: myapp
    networks:
      - isolated
    ports:
      - "3000:3000"

  monitoring:
    image: netdata/netdata
    network_mode: host # Puede monitorear el sistema host y todos los puertos del host

networks:
  isolated:
    driver: bridge
```

## Especificar redes personalizadas

En lugar de limitarte a utilizar la red por defecto de la aplicación, puedes especificar tus propias redes con la clave de nivel superior `networks`. Esto te permite crear topologías más complejas y especificar [controladores de red personalizados](/engine/extend/plugins_network/) y opciones. También puedes utilizarlo para conectar servicios a redes creadas externamente que no son gestionadas por Compose.

Cada servicio puede especificar a qué redes conectarse mediante la clave `networks` a nivel de servicio, que consiste en una lista de nombres que hacen referencia a las entradas bajo la clave de nivel superior `networks`.

El siguiente ejemplo muestra un archivo de Compose que define dos redes personalizadas. El servicio `proxy` está aislado del servicio `db`, porque no comparten una red en común. Solo `app` puede comunicarse con ambos.

```yaml
services:
  proxy:
    build: ./proxy
    networks:
      - frontend
  app:
    build: ./app
    networks:
      - frontend
      - backend
  db:
    image: postgres:latest
    networks:
      - backend

networks:
  frontend:
    driver: bridge # Especificar opciones del controlador
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: "127.0.0.1"
  backend:
    driver: custom-driver # Usar un controlador personalizado
```

Las redes se pueden configurar con direcciones IP estáticas estableciendo [ipv4_address y/o ipv6_address](/reference/compose-file/services/#ipv4_address-ipv6_address) para cada red conectada.

A las redes también se les puede asignar un [nombre personalizado](/reference/compose-file/networks/#name):

```yaml
services:
  # ...
networks:
  frontend:
    name: custom_frontend
    driver: custom-driver-1
```

### Redes internas

Establecer `internal: true` en una red la crea sin conexión a las interfaces de red del host. No tiene una puerta de enlace (gateway) por defecto para la conectividad externa. Esto es útil para servicios como bases de datos que deben ser completamente inaccesibles desde fuera de la red del contenedor:

```yaml
services:
  cache:
    image: redis
    networks:
      - isolated

  worker:
    image: myworker
    networks:
      - isolated
      - public

networks:
  isolated:
    internal: true # Sin conectividad externa
  public: # Red bridge estándar, creada por Compose al ejecutar docker compose up
```

Ten en cuenta que un servicio conectado tanto a una red interna como a una no interna (como `worker` en el ejemplo anterior) aún puede acceder a internet a través de la red no interna `public`.

### Configurar la red por defecto

En lugar de, o además de especificar tus propias redes, también puedes cambiar la configuración de la red por defecto de toda la aplicación definiendo una entrada bajo `networks` llamada `default`:

```yaml
services:
  web:
    build: .
    ports:
      - "8000:8000"
  db:
    image: postgres:latest

networks:
  default:
    driver: custom-driver-1 # Usar un controlador personalizado
```

## Usar una red externa existente

Si has creado manualmente una red bridge utilizando `docker network create`, puedes conectar tus servicios de Compose a ella marcando la red como [`external`](/reference/compose-file/networks/#external):

```yaml
services:
  # ...
networks:
  network1:
    name: my-pre-existing-network
    external: true
```

En lugar de crear `<project-name>_default`, Compose busca a red llamada `my-pre-existing-network` y conecta tus contenedores a ella.

### Conectar múltiples proyectos de Compose

Las redes externas son especialmente útiles cuando los servicios de diferentes proyectos de Compose necesitan comunicarse. Crea una red compartida una vez y luego haz referencia a ella como externa en cada proyecto:

```bash
docker network create inter-project
```

backend-compose.yaml:

```yaml
services:
  api:
    image: myapi:latest
    networks:
      - shared
      - default # Conservar también la red interna del proyecto

networks:
  shared:
    external: true
    name: inter-project
```

frontend-compose.yaml:

```yaml
services:
  web:
    image: myfrontend:latest
    environment:
      API_URL: http://api:8080 # Referencia por nombre de servicio
    networks:
      - shared

networks:
  shared:
    external: true
    name: inter-project
```

Los servicios en la misma red externa pueden comunicarse entre sí por el nombre del servicio, al igual que los servicios dentro de un solo proyecto.

> [!IMPORTANT]
>
> La red externa debe existir antes de ejecutar `docker compose up`. Si no existe, Compose falla con el error `Network not found`. Créala siempre primero con `docker network create`.

## Red híbrida

Un servicio puede pertenecer tanto a una red compartida externa como a su propia red interna de proyecto. Esto te permite exponer únicamente los servicios que deben ser accesibles desde otros proyectos, manteniendo todo lo demás, como las bases de datos, completamente aislado:

```yaml
services:
  api:
    image: myapp-api
    networks:
      - shared # Accesible desde otros proyectos
      - internal # También puede acceder a la base de datos

  database:
    image: postgres:latest
    networks:
      - internal # No expuesto en la red compartida

networks:
  shared:
    name: inter-project
    external: true
  internal: {} # Específica del proyecto, aislada
```

## DNS personalizado con `extra_hosts`

Puedes añadir asignaciones personalizadas de nombre de host a IP en el archivo `/etc/hosts` de un contenedor utilizando [`extra_hosts`](/reference/compose-file/services/#extra_hosts). Esto resulta útil cuando un servicio necesita resolver un nombre de host que no está registrado en el DNS interno de Docker. Por ejemplo, una dependencia con IP fija o un endpoint de pruebas (staging):

```yaml
services:
  app:
    image: myapp
    extra_hosts:
      - "api.staging:192.168.1.100"
      - "cache.internal:192.168.1.101"
```

Para mapear un nombre de host dinámicamente a la IP de la máquina host, utiliza el valor especial `host-gateway`:

```yaml
services:
  app:
    image: myapp
    extra_hosts:
      - "host.docker.internal:host-gateway"
```

En Linux, `host-gateway` se resuelve como la IP del host en la red bridge por defecto. En Mac y Windows, Docker proporciona esto de forma automática, por lo que `host-gateway` se resuelve en la misma dirección IP interna que `host.docker.internal`.

También puedes controlar `extra_hosts` desde variables de entorno, lo que facilita apuntar los servicios a diferentes destinos por entorno:

```yaml
services:
  app:
    image: myapp
    extra_hosts:
      - "api.service:${API_HOST:-127.0.0.1}"
      - "auth.service:${AUTH_HOST:-127.0.0.1}"
```

Donde `.env.development` podría establecer `API_HOST=localhost` y un archivo de entorno de producción podría configurar `API_HOST=10.0.1.50`.

Para verificar qué se ha inyectado, inspecciona el archivo hosts dentro del contenedor:

```bash
$ docker compose exec app cat /etc/hosts
```

## Redes multi-host

Al desplegar una aplicación de Compose en un Docker Engine con el [modo Swarm habilitado](/engine/swarm/), puedes utilizar el controlador incorporado `overlay` para permitir la comunicación multi-host. Las redes overlay siempre se crean como conectables (`attachable`). De forma opcional, puedes establecer la propiedad [`attachable`](/reference/compose-file/networks/#attachable) en `false`.

Para obtener más información, consulta la [documentación del controlador de red overlay](/engine/network/drivers/overlay/).

## Vincular contenedores (Link)

Los enlaces (links) permiten definir alias adicionales mediante los cuales un servicio es accesible desde otro servicio. No son necesarios para la comunicación básica de servicio a servicio. Por defecto, cualquier servicio puede comunicarse con cualquier otro utilizando el nombre de ese servicio. En el siguiente ejemplo, `db` es accesible desde `web` tanto a través del nombre de host `db` como de `database`:

```yaml
services:
  web:
    build: .
    links:
      - "db:database"
  db:
    image: postgres:latest
```

Consulta la [referencia de links](/reference/compose-file/services/#links) para obtener más información.

## Depuración (Debugging)

Cuando un servicio no puede comunicarse con otro, realiza los siguientes pasos en orden: primero confirma que la configuración de red sea correcta, luego confirma que los contenedores estén realmente conectados y finalmente prueba la conectividad en vivo.

### Inspeccionar mapeo de puertos

Para averiguar qué puerto del host se mapea a un puerto del contenedor, utiliza `docker compose port`:

```bash
# ¿Qué puerto del host se mapea al puerto 5432 del contenedor en db?
$ docker compose port db 5432
# Output: 0.0.0.0:8001
```

Esto resulta especialmente útil al utilizar el mapeo de puertos dinámico, donde el puerto del host cambia en cada `docker compose up`:

```yaml
services:
  web:
    image: nginx
    ports:
      - "80" # Docker asigna el puerto del host dinámicamente
```

```bash
$ docker compose port web 80
# Output: 0.0.0.0:55432
```

Al escalar un servicio, cada réplica obtiene su propio puerto dinámico. Utiliza `--index` para consultar una réplica específica:

```bash
$ docker compose up -d --scale web=3

$ docker compose port --index=1 web 80   # Output: 0.0.0.0:55001
$ docker compose port --index=2 web 80   # Output: 0.0.0.0:55002
$ docker compose port --index=3 web 80   # Output: 0.0.0.0:55003
```

Por defecto, `docker compose port` busca mapeos TCP. Si un servicio expone tanto TCP como UDP en el mismo puerto, utiliza `--protocol`:

```bash
$ docker compose port --protocol=udp myservice 53
```

### Verificar pertenencia a la red

Para comprobar qué contenedores están conectados a una red (útil al solucionar problemas de conectividad a través de redes externas o personalizadas):

```bash
$ docker network inspect <network-name>
```

### Comprobar conectividad

Si la pertenencia a la red parece correcta pero los servicios aún no pueden comunicarse entre sí, prueba la conectividad desde el interior de un contenedor en ejecución utilizando `docker compose exec`.

## Información de referencia adicional

Para obtener detalles completos de las opciones de configuración de red disponibles, consulta las siguientes referencias:

- [Elemento de nivel superior `networks`](/reference/compose-file/networks/)
- [Atributo `networks` a nivel de servicio](/reference/compose-file/services/#networks)

