Original article: How to Get A Docker Container IP Address - Explained with Examples

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

Sé lo que estás pensando: Venga, no otra publicación que explique qué es Docker, ¡Está en todas partes en estos días!

docker-i-see

Pero no se preocupe, 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 Contenedores.

Pero, ¿Alguna vez se ha preguntado cómo obtener una dirección IP del contenedor Docker?

Explicando redes en Docker


Primero, comprendamos cómo funciona las redes en Docker. Para eso, nos vamos a centrar en la red predeterminada bridge. Cuando usa Docker, si no especifica un controlador, este es el tipo de red que está usando.

docker-network
Docker network, image from understanding-docker-networking-drivers-use-cases

La red bridge funciona como una red privada interna del host para que los contenedores puedan comunicarse. El acceso externo se otorga al exponer los puertos de los contenedores.

Las redes bridge 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í mediante una red bridge creada por el usuario llamada mybridge.

Si nunca ha agregado una red en Docker, debería ver algo similar a esto:

$ docker network ls

NETWORK ID          NAME                  DRIVER              SCOPE
c3cd46f397ce        bridge                bridge              local
ad4e4c24568e        host                  host                local
1c69593fc6ac        none                  null                local

La red bridge predeterminada aparece en la lista, junto con host y none. Ignoraremos los otros dos y usaremos la red bridge cuando lleguemos a los ejemplos.

Dirección IP de un contenedor de Docker


De forma predeterminada, al contenedor se le asigna una dirección IP para cada red de Docker a la que se conecta. Y cada red se crea con una máscara de subred predeterminada, que se usa como un pool para luego proporcionar las direcciones IP.

Por lo general, Docker usa la subred predeterminada 172.17. 0.0/16  para los contenedores.

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

drawing

Ejemplo Docker


Para ilustrar esto, usaremos un entorno Hive y Hadoop, que contiene 5 contenedores Docker.

Revise el archivo docker-compose.yml  que estamos a punto de 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.0

volumes:
  namenode:
  datanode:

Desde docker-hive GitHub

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

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

¡Mucho mejor! Ahora vamos a poner en marcha esos contenedores:

docker-compose up -d

Podemos ver 5 contenedores:

$ docker ps --format \
"table {{.ID}}\t{{.Status}}\t{{.Names}}"

CONTAINER ID        STATUS                   NAMES
158741ba0339        Up 1 minutes             dockerhive_hive-metastore-postgresql
607b00c25f29        Up 1 minutes             dockerhive_namenode
2a2247e49046        Up 1 minutes             dockerhive_hive-metastore
7f653d83f5d0        Up 1 minutes (healthy)   dockerhive_hive-server
75000c343eb7        Up 1 minutes (healthy)   dockerhive_datanode

A continuación vamos a comprobar nuestras redes Docker

$ docker network ls

NETWORK ID          NAME                  DRIVER              SCOPE
c3cd46f397ce        bridge                bridge              local
9f6bc3c15568        docker-hive_default   bridge              local
ad4e4c24568e        host                  host                local
1c69593fc6ac        none                  null                local

Un momento... ¡Hay una nueva red llamada docker-hive_default!

Por defecto, docker compose configura una sola red para su aplicación. Y la red de su aplicación recibe un nombre basado en el "nombre del proyecto", que se origina a partir del nombre del directorio en el que se encuentra.

Entonces, dado que 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.

Como obtener la dirección IP de un contenedor Docker - ejemplos

Y ahora que tengo su atención, vamos a develar el misterio.

drawing

1. Usando Docker Inspect


docker inspect es una excelente manera de recuperar información de bajo nivel sobre los objetos de Docker. Puede seleccionar cualquier campo del JSON devuelto de una manera bastante sencilla.

Entonces, ¿lo usaremos para obtener la dirección IP de dockerhive_datanode?

$ docker inspect -f \
'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
75000c343eb7

172.18.0.5

¿No dije que Docker usa la subred 172.17.0.0/16 predeterminada para las redes de contenedores? ¿Por qué la dirección IP devuelta: 172.18.0.5 está fuera de ella?

Screen-Shot-2020-06-22-at-3.25.07-PM
Image created on ip-address-in-cidr-range

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

$ docker network inspect -f \
'{{range .IPAM.Config}}{{.Subnet}}{{end}}'  9f6bc3c15568

172.18.0.0/16

Ejecutamos este ejemplo en una Compute Engine VM y en esta prueba, a la red docker se le asignó 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.

Por lo tanto, 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"
drawing

Si no se dio cuenta, usamos la ayuda de jq para analizar el objeto de mapa de los Contenedores.

2. Usando Docker exec

En el siguiente ejemplo trabajaremos con el dockerhive_namenode.

$ docker exec dockerhive_namenode cat /etc/hosts

127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3      607b00c25f29

3. Dentro del contenedor Docker

$ docker exec -it dockerhive_namenode /bin/bash

# running inside the dockerhive_namenode container
ip -4 -o address

7: eth0    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0

Incluso podemos encontrar direcciones IP de otros contenedores que están dentro de la misma red:

Data node

# running inside the dockerhive_namenode container
ping dockerhive_datanode

PING dockerhive_datanode (172.18.0.5): 56 data bytes
64 bytes from 172.18.0.5: icmp_seq=0 ttl=64 time=0.092 ms

Hive mestastore

# running inside the dockerhive_namenode container
ping dockerhive_hive-metastore

PING dockerhive_hive-metastore_1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.087 ms

Hive server

# running inside the container
ping dockerhive_hive-server

PING dockerhive_hive-server (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: icmp_seq=0 ttl=64 time=0.172 ms

Tener en cuenta

Todos los ejemplos se ejecutaron en una Compute Engine VM de distribución Linux. Si los ejecuta en entornos macOS o Windows, los comandos de muestra pueden cambiar un poco.

También tenga en cuenta que esas direcciones IP en los ejemplos dados son internas a la red de ejemplo docker-hive_default. Entonces, si necesita conectarse a esos contenedores externamente, necesitará usar la IP externa de la máquina host (suponiendo que está exponiendo los puertos de los contenedores correctamente).

O si está utilizando kubernetes, por ejemplo, para administrar sus contenedores Docker, deje que kubernetes maneje las direcciones IP por usted.

* Ilustraciones de icons8.com por Murat Kalkavan.