В этой статье я описал теорию которую необходимо знать для дальнейшей работы с сетью в Docker.
Для начала я создам контейнер с nginx (если не понятно что происходит).
docker container run -d --name some-nginx -p 80:80 nginx:latest
Теперь выведу ip-адрес контейнера и ip-адрес хоста где установлен Docker.
docker inspect -f '{{ .NetworkSettings.IPAddress }}' some-nginx
172.17.0.3
ip a
172.31.144.9
Вывести список всех сетей docker в Docker (docker network ls)
В прошлой статье я упоминал что виртуальной сетей в Docker может быть намного больше чем одной, которая создаётся по умолчанию.
Для того, чтобы проверить какие вообще виртуальные сети есть в системе используется команда docker network ls, которая выведет список всех виртуальных сетей.
docker network ls
NETWORK ID NAME DRIVER SCOPE
6d18af512d4d bridge bridge local
8dd3c0368276 host host local
e4ee21b03ff4 hyper bridge local
581357de291b none null local
Просмотр информации о сети в Docker (docker network inspect)
Отлично команда выше выдала список всех сетей, но как понять какой контейнер использует ту или иную сеть. Для этого используется команда docker network inspect, где в поле Containers перечисляются контейнеры, которые используют эту сеть.
docker network inspect 6d18af512d4d
"Containers": {
"15efdb23bd4ca96be08cd6e4845a941508b231392bc2f3d0ebc57f0facd1e8f0": {
"Name": "some-nginx",
"EndpointID": "07b21011ab8e497beabf228c3208c8a77f684ee4725d8ee734fdb9a92806c53a",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
}
Как создать сеть в Docker (docker network create)
И вот пришло время создать свою собственную виртуальную сеть в Docker используя команду docker network create.
docker network create my-network1
docker network ls
3dd65f38f672 my-network1 bridge local
При создании сети я не указывал никаких настроек кроме как название этой сети. Подсеть для этой новой сети Docker задал сам автоматически. Т.е. контейнеры использующие эту сеть (my-network1) будут иметь ip-адреса вида 172.19.0.2.
docker network inspect my-network1
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
}
Если же необходимо задать какие-то конкретные значения при создании сети можно использовать следующие опции:
--driver- Тип сети (bridge,overlay,macvlan,host,none)--subnet- Указать подсеть вручную (--subnet 172.28.0.0/16)--gateway- Указать шлюз вручную (--gateway 172.28.0.1)--ip-range- Задать диапазон IP для контейнеров (--ip-range 172.28.5.0/24)
Если вдруг необходимо запретить контейнерам выход в интернет, то необходимо задать опцию --internal при создании новой сети.
Назначить сеть контейнеру
Для того чтобы назначить только что создаю сеть новому контейнеру при выполнении команды создания docker container run необходимо указать сеть при помощи параметра --network.
docker container run -d --name my-network1-nginx1 --network my-network1 nginx:alpine
Для того чтобы подключить уже запущенный контейнер к другой сети используется docker network connect.
docker network connect my-network1 some-nginx
docker network inspect my-network1
"Containers": {
"05186ff32ca1fa4f9dd01eede5293f0e7aa8676700155ffc05b7cf3b577bda54": {
"Name": "my-network1-nginx1",
"EndpointID": "4eec0b82203370114a7e3d6724f9cedf5e3629996849459b5e8e0801d331df59",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
},
"15efdb23bd4ca96be08cd6e4845a941508b231392bc2f3d0ebc57f0facd1e8f0": {
"Name": "some-nginx",
"EndpointID": "08702a00bff2d1b6381720216cd365434e97160e002677dbd91b9f6b579309d9",
"MacAddress": "02:42:ac:13:00:03",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": ""
}
},
Теперь, когда в сети my-network1 два контейнера они должны обращаться друг к другу по сети без проблем, но не иметь возможность обратиться к контейнерам из в другой сети.
docker exec -it my-network1-nginx1 sh
ping some-nginx
PING some-nginx (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.105 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.110 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.131 ms
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=63 time=0.112 ms
64 bytes from 172.17.0.2: seq=1 ttl=63 time=0.101 ms
64 bytes from 172.17.0.2: seq=2 ttl=63 time=0.125 ms
Почему контейнеры из разных сетей видят друг друга
Но как видно из вывода контейнер some-nginx-2, который в сети bridge тоже пингуется. Произошло это потому что я использую ОС CentOS, в которой по умолчанию включен firewalld, который перехватывает управление. А точнее две сети Docker находятся в одной зоне (docker) в firewalld. Поэтому трафик между всеми сетями в одной зоне разрешён. Даже если Docker добавил правила, изолирующие обе сети в iptables приоритет выше у firewalld, который пропускает весь трафик.
Самым простым решением конечно будет просто отключить firewalld в самой системе (не рекомендуется в проде).
sudo systemctl stop firewalld
sudo systemctl disable --now firewalld
И другой вариант если вы хотите сохранить работающий firewalld это исключить Docker-интерфейсы из управления firewall.
- Получаем активные зоны
sudo firewall-cmd --get-active-zonesdocker interfaces: docker0 br-e4ee21b03ff4 br-3dd65f38f672 - Удалить все Docker-интерфейсы
sudo firewall-cmd --permanent --remove-interface=docker0 sudo firewall-cmd --permanent --remove-interface=br-e4ee21b03ff4 sudo firewall-cmd --permanent --remove-interface=br-3dd65f38f672 - Перечитываем правила
sudo firewall-cmd --reload - Перезапускаем Docker
sudo systemctl restart docker
Отключить сеть контейнера
Если нужно отключить сеть у контейнера выполняем команду docker network disconnect.
docker network disconnect bridge some-nginx


Комментарии