Cómo obtener una dirección IP de un contenedor Docker – Explicado con ejemplos

Docker proporciona la capacidad de empaquetar y ejecutar una aplicación en un entorno poco aislado llamado contenedor.

Sé lo que puedes estar pensando – vamos, no otro post explicando lo que es Docker, está en todas partes estos días!

docker-i-see

Pero no te preocupes, nos estamos saltando esa introducción básica. El público objetivo de este artículo ya debería tener una comprensión básica de lo que son Docker y los contenedores.

Pero, ¿te has preguntado alguna vez cómo obtener una dirección IP de un contenedor Docker?

Explicación de la red Docker

Primero, vamos a entender cómo funciona la red Docker. Para ello vamos a centrarnos en la red por defecto bridge. Cuando se utiliza Docker, si no se especifica un controlador este es el tipo de red que se utiliza.

docker-network
Red Docker de: understanding-docker-networking-drivers-use-cases

La red bridgefunciona como una red privada interna al host para que los contenedores en él puedan comunicarse. El acceso externo se realiza exponiendo los puertos a los contenedores.

Las redes puente se utilizan cuando sus aplicaciones se ejecutan en contenedores independientes que necesitan comunicarse.

En la imagen de arriba db y web pueden comunicarse entre sí en una red puente creada por el usuario llamada mybridge.

Si nunca has añadido una red en Docker deberías ver algo similar a esto:

$ docker network lsNETWORK ID NAME DRIVER SCOPEc3cd46f397ce bridge bridge localad4e4c24568e host host local1c69593fc6ac none null local

La red por defecto bridge aparece en la lista, junto con host y none. Ignoraremos las otras dos, y usaremos la red bridge cuando lleguemos a los ejemplos.

Dirección IP del contenedor Docker

Por defecto, al contenedor se le asigna una dirección IP para cada red Docker a la que se conecta. Y cada red se crea con una máscara de subred por defecto, utilizándola como pool posteriormente para ceder las direcciones IP.

Por lo general, Docker utiliza la subred por defecto 172.17. 0.0/16 para la red de contenedores.

Ahora, para entenderlo mejor, ejecutaremos un caso de uso real.

Dibujo

Ejemplo de Docker

Para ilustrarlo, utilizaremos un entorno Hive y Hadoop, que contiene 5 contenedores Docker.

Mira el archivo docker-compose.ymlque vamos a ejecutar:

version: "3"services: namenode: image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8 volumes: - namenode:/hadoop/dfs/name environment: - CLUSTER_NAME=test env_file: - ./hadoop-hive.env ports: - "50070:50070" datanode: image: bde2020/hadoop-datanode:2.0.0-hadoop2.7.4-java8 volumes: - datanode:/hadoop/dfs/data env_file: - ./hadoop-hive.env environment: SERVICE_PRECONDITION: "namenode:50070" ports: - "50075:50075" hive-server: image: bde2020/hive:2.3.2-postgresql-metastore env_file: - ./hadoop-hive.env environment: HIVE_CORE_CONF_javax_jdo_option_ConnectionURL: "jdbc:postgresql://hive-metastore/metastore" SERVICE_PRECONDITION: "hive-metastore:9083" ports: - "10000:10000" hive-metastore: image: bde2020/hive:2.3.2-postgresql-metastore env_file: - ./hadoop-hive.env command: /opt/hive/bin/hive --service metastore environment: SERVICE_PRECONDITION: "namenode:50070 datanode:50075 hive-metastore-postgresql:5432" ports: - "9083:9083" hive-metastore-postgresql: image: bde2020/hive-metastore-postgresql:2.3.0volumes: namenode: datanode:

Del GitHub de docker-hive

Nadie quiere leer un archivo de configuración ENORME, ¿verdad? Así que aquí tienes una imagen:

Screen-Shot-2020-06-21-at-2.48.18-PM

¡Mucho mejor! Ahora vamos a arrancar esos contenedores:

docker-compose up -d

Podemos ver 5 contenedores:

$ docker ps --format \"table {{.ID}}\t{{.Status}}\t{{.Names}}"CONTAINER ID STATUS NAMES158741ba0339 Up 1 minutes dockerhive_hive-metastore-postgresql607b00c25f29 Up 1 minutes dockerhive_namenode2a2247e49046 Up 1 minutes dockerhive_hive-metastore7f653d83f5d0 Up 1 minutes (healthy) dockerhive_hive-server75000c343eb7 Up 1 minutes (healthy) dockerhive_datanode

A continuación vamos a comprobar nuestras redes Docker:

$ docker network lsNETWORK ID NAME DRIVER SCOPEc3cd46f397ce bridge bridge local9f6bc3c15568 docker-hive_default bridge localad4e4c24568e host host local1c69593fc6ac none null local

¡Espera un momento… hay una nueva red llamada docker-hive_default!

Por defecto docker compose configura una única red para tu aplicación. Y la red de tu app recibe un nombre basado en el «nombre del proyecto», originado por el nombre del directorio en el que vive.

Así que como nuestro directorio se llama docker-hive, esto explica la nueva red.

A continuación algunos ejemplos sobre cómo obtener la dirección IP de Docker.

Cómo obtener la dirección IP de un contenedor Docker – ejemplos

Y ahora que tengo vuestra atención, vamos a desvelar el misterio.

Dibujo

Usando Docker Inspect

Docker inspect es una gran manera de recuperar información de bajo nivel sobre los objetos Docker. Puedes escoger cualquier campo del JSON devuelto de una manera bastante sencilla.

Entonces, ¿lo utilizamos para obtener la dirección IP del dockerhive_datanode?

$ docker inspect -f \'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 000c343eb7172.18.0.5

¿No decías que Docker utiliza la subred por defecto 172.17. 0.0/16 para la red de contenedores? ¿Por qué es la dirección IP devuelta: 172.18.0.5 fuera de ella?

Screen-Shot-2020-06-22-at-3.25.07-PM
Imagen creada en ip-address-in-cidr-range

Para responder a eso tenemos que mirar nuestra configuración de red:

$ docker network inspect -f \'{{range .IPAM.Config}}{{.Subnet}}{{end}}' 9f6bc3c15568172.18.0.0/16

Ejecutamos este ejemplo en una VM Compute Engine, y en esta prueba, la red de Docker tenía asignada una subred diferente: 172.18.0.0/16. Eso lo explica:

Además, también podemos buscar todas las direcciones IP dentro de la red docker-hive_default.

Así no necesitamos buscar la IP de cada Contenedor individualmente:

$ docker network inspect -f \'{{json .Containers}}' 9f6bc3c15568 | \jq '. | .Name + ":" + .IPv4Address'"dockerhive_hive-metastore-postgresql:172.18.0.6/16""dockerhive_hive-metastore:172.18.0.2/16""dockerhive_namenode:172.18.0.3/16""dockerhive_datanode:172.18.0.5/16""dockerhive_hive-server:172.18.0.4/16"
dibujando

Por si no te has dado cuenta, hemos usado jq help para parsear el objeto map Containers.

Usando Docker exec

En el siguiente ejemplo trabajaremos con el dockerhive_namenode.

$ docker exec dockerhive_namenode cat /etc/hosts127.0.0.1 localhost::1 localhost ip6-localhost ip6-loopbackfe00::0 ip6-localnetff00::0 ip6-mcastprefixff02::1 ip6-allnodesff02::2 ip6-allrouters172.18.0.3 607b00c25f29

Dentro del contenedor Docker

$ docker exec -it dockerhive_namenode /bin/bash# running inside the dockerhive_namenode containerip -4 -o address7: eth0 inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0

Incluso podemos encontrar las direcciones IP de otros contenedores que estén dentro de un contenedor en la misma red:

Nodo de datos

# running inside the dockerhive_namenode containerping dockerhive_datanodePING dockerhive_datanode (172.18.0.5): 56 data bytes64 bytes from 172.18.0.5: icmp_seq=0 ttl=64 time=0.092 ms

Hive mestastore

# running inside the dockerhive_namenode containerping dockerhive_hive-metastorePING dockerhive_hive-metastore_1 (172.18.0.2): 56 data bytes64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.087 ms

Servidor de colmena

# running inside the containerping dockerhive_hive-serverPING dockerhive_hive-server (172.18.0.4): 56 data bytes64 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.172 ms

Wrap up

Todos los ejemplos se han ejecutado en una VM Compute Engine de distribución linux. Si los ejecutas en entornos macOS o Windows los comandos de ejemplo pueden cambiar un poco.

Ten en cuenta también que esas Direcciones IP en los ejemplos dados son internas a la red docker-hive_default de ejemplo. Así que si usted tiene un caso de uso para conectarse a esos contenedores externamente, tendría que utilizar la IP externa de la máquina anfitriona (suponiendo que usted está exponiendo los puertos de los contenedores correctamente).
O si estás usando kubernetes, por ejemplo, para gestionar tus contenedores Docker, deja que se encargue de las direcciones IP por ti kubernetes-expose-external-ip-address

* Ilustraciones de icons8.com por Murat Kalkavan.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *