Як отримати IP-адресу контейнера Docker - пояснено на прикладах

Docker надає можливість упаковувати та запускати додаток у вільно ізольованому середовищі, яке називається контейнером.

Я знаю, про що ви можете подумати - давай, а не черговий допис, що пояснює, що таке Docker, він сьогодні всюди!

Але не хвилюйтесь, ми пропускаємо це основне введення. Цільова аудиторія цієї статті вже повинна добре знати, що таке Docker та контейнери.

Але чи замислювались ви коли-небудь про те, як отримати IP-адресу контейнера Docker?

Пояснення мережі Docker

Спочатку давайте розберемося, як працює мережа Docker. Для цього ми зосередимося на bridgeмережі за замовчуванням . Якщо ви використовуєте Docker, якщо ви не вказали драйвер, це тип мережі, який ви використовуєте.

bridgeМережа працює в якості приватної мережі внутрішнього хосту так контейнери на ній можуть спілкуватися. Зовнішній доступ надається шляхом оголення портів контейнерами.

Мостові мережі використовуються, коли ваші програми працюють в автономних контейнерах, які потребують зв’язку.

На малюнку вище dbі webможе спілкуватися один з одним за допомогою створеної користувачем мостової мережі mybridge.

Якщо ви ніколи не додавали мережу в Docker, ви повинні побачити щось подібне до цього:

$ docker network ls NETWORK ID NAME DRIVER SCOPE c3cd46f397ce bridge bridge local ad4e4c24568e host host local 1c69593fc6ac none null local

У bridgeсписку вказано мережу за замовчуванням , а також hostі none. Ми будемо ігнорувати інші два і використовуватимемо bridgeмережу, коли дійдемо до прикладів.

IP-адреса контейнера Docker

За замовчуванням контейнеру присвоюється IP-адреса для кожної мережі Docker, до якої він підключається. І кожна мережа створюється з маскою підмережі за замовчуванням, використовуючи її як пул згодом для видачі IP-адрес.

Зазвичай Docker використовує 172.17 за замовчуванням . 0,0 / 16 підмережа для роботи з контейнерами.

Тепер, щоб краще зрозуміти це, ми виконаємо реальний випадок використання.

малювання

Приклад Докера

Щоб проілюструвати це, ми використаємо середовище Hive та Hadoop, що містить 5 контейнерів Docker.

Перевірте docker-compose.ymlфайл, який ми збираємось виконати:

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: 

З док-вулика GitHub

Ніхто не хоче читати ВЕЛИЧЕЗНИЙ конфігураційний файл, так? Тож ось картинка:

Значно краще! Тепер давайте запустимо ці контейнери:

docker-compose up -d 

Ми можемо побачити 5 контейнерів:

$ 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

Далі перевіримо наші мережі 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

Зачекайте хвилинку ... називається нова мережа docker-hive_default!

За замовчуванням docker compose встановлює єдину мережу для вашого додатка. А мережі вашої програми надається ім’я на основі «назви проекту», що походить від назви каталогу, в якому вона живе.

Отож, оскільки наш каталог названий docker-hive, це пояснює нову мережу.

Далі кілька прикладів того, як отримати IP-адресу Docker.

Як отримати IP-адресу контейнера Docker - приклади

І тепер, коли у мене є ваша увага, ми збираємось розкрити таємницю.

малювання

1. За допомогою Docker Inspect

Перевірка Docker - чудовий спосіб отримати низькорівневу інформацію про об’єкти Docker. Ви можете вибрати будь-яке поле з повернутого JSON досить просто.

Тож чи будемо ми використовувати його для отримання IP-адреси від dockerhive_datanode?

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

Хіба ви не казали, що Docker використовує 172.17 за замовчуванням . 0,0 / 16 підмережа для роботи з контейнерами? Чому повернута IP-адреса: 172.18.0.5  за її межами?

Щоб відповісти, що ми маємо переглянути наші налаштування мережі:

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

Ми виконали цей приклад у віртуальній машині Compute Engine, і в цьому тесті мережі докерів було призначено іншу підмережу: 172.18.0.0/16 . Це пояснює це!

Крім того, ми також можемо шукати всі IP-адреси всередині docker-hive_defaultмережі.

Тому нам не потрібно шукати IP кожного контейнера окремо:

$ 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"
малювання

Якщо ви цього не помітили, ми використали довідку jq для синтаксичного аналізу Containersоб’єкта карти.

2. Використання програми Docker exec

У наступному прикладі ми будемо працювати з 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. Всередині контейнера 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

Ми навіть можемо знайти IP-адреси інших контейнерів, які знаходяться всередині контейнера в одній мережі:

Вузол даних

# 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

Вулик 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

Сервер вуликів

# 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

Загорнути

Усі приклади виконувались у дистрибутиві Linux Compute Engine VM. Якщо ви виконуєте їх у середовищі macOS або Windows, зразки команд можуть трохи змінитися.

Також майте на увазі, що ці IP-адреси у наведених прикладах є внутрішніми для вибіркової docker-hive_defaultмережі. Отже, якщо у вас є варіант використання для зовнішнього підключення до цих контейнерів, вам потрібно буде використовувати зовнішній IP-адресу хост-машини (за умови, що ви правильно виставляєте порти контейнерів).

Або якщо ви використовуєте kubernetes, наприклад, для управління контейнерами Docker, нехай він обробляє IP-адреси для вас kubernetes-expose-external-ip-address?

* Ілюстрації з icons8.com Мурата Калкавана.