Conceptos Básicos de Redes en Docker

DockerBeginner
Practicar Ahora

Introducción

En esta práctica de laboratorio, exploraremos los fundamentos de las redes en Docker. Las redes de Docker permiten que los contenedores se comuniquen entre sí y con el mundo exterior. Cubriremos varios tipos de redes, la creación de redes personalizadas, la conexión de contenedores y la gestión de configuraciones de red. Esta experiencia práctica le proporcionará una base sólida en los conceptos y prácticas de redes de Docker.

Comprensión de los Tipos de Red de Docker

Docker proporciona varios controladores de red integrados. Comencemos examinando las redes predeterminadas en su sistema.

En su terminal, ejecute el siguiente comando para listar todas las redes de Docker disponibles:

docker network ls

Este comando enumera todas las redes que Docker ha creado en su sistema. Debería ver una salida similar a esta:

NETWORK ID     NAME      DRIVER    SCOPE
79dce413aafd   bridge    bridge    local
91199fc6ad2e   host      host      local
1078d2c781b6   none      null      local

Analicemos los tipos de red predeterminados:

  1. bridge: Este es el controlador de red por defecto. Cuando inicia un contenedor sin especificar una red, se conecta automáticamente a la red bridge. Los contenedores en la misma red bridge pueden comunicarse entre sí utilizando sus direcciones IP.

  2. host: Este controlador elimina el aislamiento de red entre el contenedor y el host de Docker. El contenedor comparte el espacio de nombres de red del host, lo que significa que utiliza directamente la dirección IP y el espacio de puertos del host. Esto puede ser útil para optimizar el rendimiento en ciertos escenarios.

  3. none: Este controlador desactiva todas las funciones de red para un contenedor. Los contenedores que utilizan este tipo de red no tendrán acceso a redes externas ni a otros contenedores. Es útil cuando se desea aislar completamente un contenedor.

La columna SCOPE indica si la red está limitada a un solo host (local) o si puede extenderse a través de múltiples hosts en un enjambre de Docker (swarm).

Inspección de la Red Bridge Predeterminada

Ahora que hemos visto la lista de redes, echemos un vistazo más de cerca a la red bridge predeterminada. Esta red es creada automáticamente por Docker y es utilizada por los contenedores a menos que se especifique lo contrario.

Ejecute el siguiente comando para inspeccionar la red bridge:

docker network inspect bridge

Este comando proporciona información detallada sobre la red bridge, incluyendo su subred, puerta de enlace (gateway) y contenedores conectados. Verá una salida similar a esta (truncada para mayor brevedad):

[
  {
    "Name": "bridge",
    "Id": "79dce413aafdd7934fa3c1d0cc97decb823891ce406442b7d51be6126ef06a5e",
    "Created": "2024-08-22T09:58:39.747333789+08:00",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
      "Driver": "default",
      "Options": null,
      "Config": [
        {
          "Subnet": "172.17.0.0/16",
          "Gateway": "172.17.0.1"
        }
      ]
    },
    "Internal": false,
    "Attachable": false,
    "Ingress": false,
    "ConfigFrom": {
      "Network": ""
    },
    "ConfigOnly": false,
    "Containers": {},
    "Options": {
      "com.docker.network.bridge.default_bridge": "true",
      "com.docker.network.bridge.enable_icc": "true",
      "com.docker.network.bridge.enable_ip_masquerade": "true",
      "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
      "com.docker.network.bridge.name": "docker0",
      "com.docker.network.driver.mtu": "1500"
    },
    "Labels": {}
  }
]

Analicemos algunos datos clave de esta salida:

  • Subnet: La subred utilizada por los contenedores en esta red es 172.17.0.0/16. Esto significa que a los contenedores se les asignarán direcciones IP dentro de este rango.
  • Gateway: La puerta de enlace para esta red es 172.17.0.1. Esta es la dirección IP que los contenedores utilizan para comunicarse con redes fuera de la suya.
  • Containers: Este campo está vacío porque aún no hemos iniciado ningún contenedor.
  • Options: Estas son varias opciones de configuración para la red bridge. Por ejemplo, enable_icc establecido en "true" significa que se permite la comunicación entre contenedores (inter-container communication) en esta red.

Comprender esta información es crucial al solucionar problemas de red o cuando necesita configurar sus contenedores para comunicarse con rangos de IP específicos.

Creación de una Red Bridge Personalizada

Aunque la red bridge predeterminada es adecuada para muchos casos de uso, la creación de redes personalizadas permite un mejor aislamiento y control. Las redes personalizadas son particularmente útiles cuando desea agrupar contenedores relacionados o cuando necesita controlar qué contenedores pueden comunicarse entre sí.

Vamos a crear una red bridge personalizada llamada my-network:

docker network create --driver bridge my-network

Este comando crea una nueva red bridge. La opción --driver bridge es opcional aquí porque bridge es el controlador predeterminado, pero se incluye para mayor claridad.

Ahora, verifiquemos que nuestra nueva red ha sido creada:

docker network ls

Debería ver my-network en la lista de redes:

NETWORK ID     NAME         DRIVER    SCOPE
1191cb61c989   bridge       bridge    local
91199fc6ad2e   host         host      local
47ac4e684a72   my-network   bridge    local
1078d2c781b6   none         null      local

Nuestra nueva red my-network aparece en la lista, confirmando que se creó con éxito. Esta red ahora está disponible para que los contenedores se conecten a ella.

Conexión de Contenedores a las Redes

Ahora que tenemos nuestra red personalizada, vamos a crear dos contenedores y conectarlos a ella. Usaremos la imagen de nginx para este ejemplo, que proporciona un servidor web ligero.

Ejecute los siguientes comandos para crear dos contenedores:

docker run -d --name container1 --network my-network nginx
docker run -d --name container2 --network my-network nginx

Analicemos estos comandos:

  • -d: Esta bandera ejecuta el contenedor en modo "detached", lo que significa que se ejecuta en segundo plano.
  • --name: Esto asigna un nombre a nuestro contenedor, facilitando su referencia posterior.
  • --network: Esto especifica a qué red debe conectarse el contenedor.
  • nginx: Este es el nombre de la imagen que estamos usando para crear nuestros contenedores.

Estos comandos crean dos contenedores en segundo plano llamados container1 y container2, ambos conectados a nuestra red my-network.

Verifiquemos que los contenedores se están ejecutando y están conectados a nuestra red:

docker ps

Este comando enumera todos los contenedores en ejecución. Debería ver ambos contenedores en la salida:

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
1234567890ab   nginx     "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds    80/tcp    container2
abcdef123456   nginx     "/docker-entrypoint.…"   20 seconds ago   Up 19 seconds   80/tcp    container1

Esta salida muestra que ambos contenedores están ejecutando la imagen de Nginx y están exponiendo el puerto 80 dentro del contenedor.

Prueba de Comunicación entre Contenedores

Uno de los beneficios clave de las redes de Docker es que los contenedores en la misma red pueden comunicarse entre sí utilizando sus nombres de contenedor como nombres de host (hostnames). Esto facilita la configuración de la comunicación entre servicios sin necesidad de conocer sus direcciones IP.

Probemos esto usando el container1 para enviar una solicitud al container2:

docker exec container1 curl -s container2

Analicemos este comando:

  • docker exec: Esto le indica a Docker que ejecute un comando dentro de un contenedor en ejecución.
  • container1: Este es el nombre del contenedor en el que queremos ejecutar el comando.
  • curl -s container2: Este es el comando que estamos ejecutando dentro del contenedor. Envía una solicitud GET al container2 y la bandera -s hace que curl funcione en modo silencioso.

Este comando ejecuta el comando curl dentro de container1, enviando una solicitud a container2. Debería ver el HTML de la página de bienvenida predeterminada de Nginx en la salida:

<!doctype html>
<html>
  <head>
    <title>Welcome to nginx!</title>
    <style>
      html {
        color-scheme: light dark;
      }
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>Welcome to nginx!</h1>
    <p>
      If you see this page, the nginx web server is successfully installed and
      working. Further configuration is required.
    </p>

    <p>
      For online documentation and support please refer to
      <a href="http://nginx.org/">nginx.org</a>.<br />
      Commercial support is available at
      <a href="http://nginx.com/">nginx.com</a>.
    </p>

    <p><em>Thank you for using nginx.</em></p>
  </body>
</html>

Esta respuesta exitosa demuestra que el container1 puede comunicarse con el container2 utilizando su nombre de contenedor. El servidor DNS embebido de Docker resuelve el nombre del contenedor a su dirección IP dentro de la red.

Exposición de Puertos de Contenedores

Por defecto, los contenedores en una red personalizada pueden comunicarse entre sí, pero no son accesibles desde fuera del host de Docker. Para que un contenedor sea accesible desde el host o redes externas, necesitamos exponer sus puertos.

Vamos a crear un nuevo contenedor con un puerto expuesto:

docker run -d --name exposed-container -p 8080:80 --network my-network nginx

Analicemos este comando:

  • -d: Ejecuta el contenedor en modo en segundo plano.
  • --name exposed-container: Nombra al contenedor como "exposed-container".
  • -p 8080:80: Mapea el puerto 80 dentro del contenedor al puerto 8080 en el host.
  • --network my-network: Conecta el contenedor a nuestra red personalizada.
  • nginx: Utiliza la imagen de Nginx.

Este comando crea un nuevo contenedor llamado exposed-container, mapea el puerto 80 del contenedor al puerto 8080 del host y lo conecta a nuestra red my-network.

Ahora, puede acceder al servidor Nginx de este contenedor desde su máquina host abriendo un navegador web y navegando a http://localhost:8080, o utilizando curl:

curl localhost:8080

Debería ver el mismo HTML de la página de bienvenida de Nginx que antes. Esta vez, sin embargo, estamos accediendo al contenedor directamente desde el host, no desde otro contenedor.

Uso de la Red del Host (Host Networking)

Para escenarios en los que desea que un contenedor comparta la pila de red del host, puede utilizar el controlador de red host. Esto elimina el aislamiento de red entre el contenedor y el host, lo cual puede ser útil para ciertas aplicaciones, pero debe usarse con cuidado debido a posibles conflictos de puertos.

Vamos a crear un contenedor utilizando la red del host:

docker run -d --name host-networked --network host nginx

Este comando crea un nuevo contenedor llamado host-networked utilizando la red host. Tenga en cuenta que no puede usar -p con la red host, ya que el contenedor ya está utilizando las interfaces de red del host.

Para verificar que el contenedor está utilizando la red host, podemos inspeccionar su configuración de red:

docker inspect --format '{{.HostConfig.NetworkMode}}' host-networked

Este comando inspecciona el contenedor y formatea la salida para mostrar solo el NetworkMode. Debería devolver host, confirmando que el contenedor está utilizando la red del host.

Al usar la red host, el contenedor comparte la dirección IP del host y puede acceder directamente a todas las interfaces de red del host. Esto puede ser útil para maximizar el rendimiento, pero también significa que cualquier puerto que use el contenedor se abrirá directamente en el host, lo que podría provocar conflictos si no se tiene cuidado.

Resumen

En este laboratorio, exploramos los fundamentos de las redes en Docker. Cubrimos varios tipos de redes, la creación de redes personalizadas, la conexión de contenedores, la prueba de comunicación entre contenedores, la exposición de puertos de contenedores y el uso de la red host. Estos conceptos forman la base de las redes en Docker y son esenciales para diseñar y gestionar aplicaciones contenedorizadas.

Aprendimos cómo:

  • Listar e inspeccionar redes de Docker.
  • Crear redes bridge personalizadas.
  • Conectar contenedores a las redes.
  • Probar la comunicación entre contenedores.
  • Exponer puertos de contenedores al host.
  • Utilizar la red host para los contenedores.

Comprender estos conceptos de red le ayudará a diseñar aplicaciones contenedorizadas más robustas y seguras. A medida que continúe trabajando con Docker, encontrará escenarios de red más avanzados, pero los principios que hemos cubierto aquí servirán como una base sólida para su camino en la orquestación de contenedores y la arquitectura de microservicios.

Recuerde que las redes de Docker son una herramienta poderosa que le permite crear entornos aislados para sus aplicaciones, permitiendo al mismo tiempo una comunicación controlada entre contenedores y con el mundo exterior. Practique estos conceptos y explore temas más avanzados para volverse experto en la gestión de redes de Docker.