Перейти к основному содержимому

Получение информации о сети из Docker

· 4 мин. чтения

1. Обзор

Одной из главных особенностей Docker является создание и изоляция сетей.

В этом руководстве мы увидим, как извлекать информацию о сетях и контейнерах, которые они содержат.

2. Сеть в Docker

Когда мы запускаем контейнер Docker, мы можем определить, какие порты мы хотим открыть для внешнего мира. Это означает, что мы используем (или создаем) изолированную сеть и помещаем внутрь наш контейнер. Мы можем решить, как мы будем общаться как с этой сетью, так и внутри нее.

Давайте создадим несколько контейнеров и настроим сетевое взаимодействие между ними. Все они будут внутренне работать на порту 8080 и будут размещены в двух сетях.

На каждом из них будет размещен простой HTTP-сервис «Hello World»:

version: "3.5"

services:
test1:
image: node
command: node -e "const http = require('http'); http.createServer((req, res) => { res.write('Hello from test1\n'); res.end() }).listen(8080)"
ports:
- "8080:8080"
networks:
- network1
test2:
image: node
command: node -e "const http = require('http'); http.createServer((req, res) => { res.write('Hello from test2\n'); res.end() }).listen(8080)"
ports:
- "8081:8080"
networks:
- network1
- network2
test3:
image: node
command: node -e "const http = require('http'); http.createServer((req, res) => { res.write('Hello from test3\n'); res.end() }).listen(8080)"
ports:
- "8082:8080"
networks:
- network2

networks:
network1:
name: network1
network2:
name: network2

Вот схема этих контейнеров для более наглядного представления:

./bd437bcba1fe3441d93059cd1b9eadc3.png

Запустим их все командой docker-compose :

$ docker-compose up -d
Starting bael_test2_1 ... done
Starting bael_test3_1 ... done
Starting bael_test1_1 ... done

3. Проверка сети

Во-первых, давайте перечислим все доступные сети Docker:

$ docker network ls
NETWORK ID NAME DRIVER SCOPE
86e6a8138c0d bridge bridge local
73402de5766c host host local
e943f7124776 network1 bridge local
3b9a28673a16 network2 bridge local
9361d16a834a none null local

Мы видим мостовую сеть, которая используется по умолчанию, когда мы используем команду запуска docker . Кроме того, мы можем видеть сети, которые мы создали с помощью команды docker-compose .

Давайте проверим их с помощью команды docker inspect :

$ docker inspect network1 network2
[
{
"Name": "network1",
"Id": "e943f7124776d45a1481ee26795b2dba3f2ab51f000d875a179a99ce832eee9f",
"Created": "2020-08-22T10:38:22.198709146Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
// output cutout for brevity
}
],
{
"Name": "network2",
// output cutout for brevity
}
}

Это приведет к длинным и подробным выводам. Нам редко нужна вся эта информация. К счастью, мы можем отформатировать его с помощью шаблонов Go и извлечь только те элементы, которые нам нужны. Получим только подсеть network1:

$ docker inspect -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}' network1
172.22.0.0/16

4. Проверка контейнера

Точно так же мы можем осмотреть конкретный контейнер. Сначала перечислим все контейнеры с их идентификаторами:

$ docker ps --format 'table {{.ID}}\t{{.Names}}'
CONTAINER ID NAMES
78c10f03ad89 bael_test2_1
f229dde68f3b bael_test3_1
b09a8f47e2a8 bael_test1_1

Теперь мы будем использовать идентификатор контейнера в качестве аргумента команды проверки , чтобы найти его IP-адрес. Как и в случае с сетями, мы можем форматировать вывод, чтобы получить только ту информацию, которая нам нужна. Проверим второй контейнер и его адрес в обеих созданных нами сетях:

$ docker inspect 78c10f03ad89 --format '{{.NetworkSettings.Networks.network1.IPAddress}}'
172.22.0.2
$ docker inspect 78c10f03ad89 --format '{{.NetworkSettings.Networks.network2.IPAddress}}'
172.23.0.3

В качестве альтернативы мы можем распечатать хосты прямо из контейнера с помощью команды docker exec :

$ docker exec 78c10f03ad89 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.22.0.2 78c10f03ad89
172.23.0.3 78c10f03ad89

5. Связь между контейнерами

Используя знания о наших сетях Docker, мы можем установить связь между контейнерами в одной сети.

Во-первых, давайте зайдем внутрь контейнера «test1»:

$ docker exec -it b09a8f47e2a8 /bin/bash

Затем используйте curl для отправки запроса в контейнер «test2»:

root@b09a8f47e2a8:/# curl 172.22.0.2:8080
Hello from test2

Поскольку мы находимся внутри сети Docker, мы также можем использовать псевдоним вместо IP-адреса. Встроенный DNS-сервис Docker разрешит нам адрес:

root@b09a8f47e2a8:/# curl test2:8080
Hello from test2

Имейте в виду, что мы не можем подключиться к контейнеру «test3», потому что он находится в другой сети. Время подключения по IP-адресу истекает:

root@b09a8f47e2a8:/# curl 172.23.0.2:8080

Подключение по псевдониму также не удастся, потому что служба DNS не распознает его:

root@b09a8f47e2a8:/# curl test3:8080
curl: (6) Could not resolve host: test3

Чтобы это работало, нам нужно добавить контейнер «test3» в «network1» (извне контейнера):

$ docker network connect --alias test3 network1 f229dde68f3b

Теперь запрос к «test3» будет работать корректно:

root@b09a8f47e2a8:/# curl test3:8080
Hello from test3

6. Заключение

В этом руководстве мы увидели, как настроить сети для контейнеров Docker, а затем запросить информацию о них.