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 Мурата Калкавана.