Как да получите IP адрес на контейнер на Docker - обяснено с примери

Docker предоставя възможност за пакетиране и стартиране на приложение в слабо изолирана среда, наречена контейнер.

Знам какво може би си мислите - хайде, не друга публикация, обясняваща какво е Docker, тя е навсякъде в наши дни!

Но не се притеснявайте, ние пропускаме това основно въведение. Целевата аудитория за тази статия вече трябва да има основно разбиране за това какво представляват Docker и контейнери.

Замисляли ли сте се някога как да получите IP адрес на Docker Container?

Обяснено от мрежата на 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 подмрежа за мрежа от контейнери.

Сега, за да го разберем по-добре, ще изпълним истински случай на употреба.

рисуване

Пример за Docker

За да илюстрираме това, ще използваме среда 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 VM и в този тест на докер мрежата беше зададена различна подмрежа: 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 help, за да анализираме 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

Кошер местасторе

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