Что на самом деле делает параметр --net = host в команде Docker?


90

Я немного новичок в Docker. Я не смог найти четкого описания того, что эта опция делает в команде docker run, и немного запутался в этом.

Можем ли мы использовать его для доступа к приложениям, работающим в контейнерах докеров, без указания порта? В качестве примера, если я запускаю веб-приложение, развернутое через образ докера на порту 8080, используя параметр -p 8080:8080в команде запуска докера, я знаю, что мне придется получить к нему доступ через порт 8080 в контейнерах Docker ip / theWebAppName. Но я действительно не могу придумать, как --net=hostработает опция.

Ответы:


127

После установки докера у вас по умолчанию 3 сети:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

Я стараюсь не усложнять. Поэтому, если вы запустите контейнер по умолчанию, он будет создан внутри сети моста (docker0).

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

В dockerfile jenkins показаны порты 8080и 50000. Эти порты открыты для контейнера в его сети моста. Таким образом, все внутри этой мостовой сети может получить доступ к контейнеру через порт 8080и 50000. Все в мостовой сети находится в частном диапазоне. "Subnet": "172.17.0.0/16",Если вы хотите получить к ним доступ извне, вы должны сопоставить порты -p 8080:8080. Это сопоставит порт вашего контейнера с портом вашего реального сервера (хост-сети). Таким образом, доступ к вашему серверу 8080будет направлен в вашу мостовую сеть через порт 8080.

Теперь у вас также есть хост-сеть. Что не создает контейнеры для сети контейнеров. Итак, если вы запустите контейнер в хост-сети, он будет выглядеть так (он первый):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

Разница в портах. Теперь ваш контейнер находится внутри вашей хост-сети. Поэтому, если вы откроете порт 8080на своем хосте, вы сразу получите доступ к контейнеру.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

Я открыл порт 8080в своем брандмауэре, и когда я теперь обращаюсь к своему серверу через порт, 8080я обращаюсь к своим jenkins. Я думаю, что этот блог также полезен, чтобы лучше понять его.


4
Можно ли добавить эту опцию --net=hostв Dockerfile?
AnirbanDebnath

6
@AnirbanDebnath Я не думаю , что можно поставить его в dockerfile , но так как докер v17 вы можете использовать его в качестве параметра для вашего Docker сборки: docker build --network=host. Указанная хост-сеть для сборки докеров предназначена только для загрузки пакетов, необходимых для сборки образа. Если вы хотите запустить свой контейнер в сети хоста, вам все равно необходимо определить параметр --network = host.
lvthillo

Да @AnirbanDebnath, это разрешено в Dockerfile. например, в версии 3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish

Это файл Docker-Compose, в котором описывается, как запустить контейнер. Это не Dockerfile. Но действительно, там это возможно и делает то же самое, что и docker run --network = host
lvthillo

27

Эта --net=hostопция используется для того, чтобы программы внутри контейнера Docker выглядели так, как будто они работают на самом хосте, с точки зрения сети. Это дает контейнеру больший доступ к сети, чем обычно.

Обычно вам необходимо перенаправить порты с хост-машины в контейнер, но когда контейнеры совместно используют сеть хоста, любая сетевая активность происходит непосредственно на хост-машине - так же, как если бы программа выполнялась локально на хосте, а не внутри контейнер.

Хотя это означает, что вам больше не нужно открывать порты и сопоставлять их с портами контейнера, это означает, что вам нужно отредактировать свои файлы Docker, чтобы настроить порты, которые прослушивает каждый контейнер, чтобы избежать конфликтов, поскольку у вас не может быть двух контейнеров, работающих на одном и том же порт хоста. Однако настоящая причина этого варианта - запуск приложений, которым необходим сетевой доступ, который трудно перенаправить в контейнер на уровне порта.

Например, если вы хотите запустить DHCP-сервер, вам необходимо иметь возможность прослушивать широковещательный трафик в сети и извлекать MAC-адрес из пакета. Эта информация теряется во время процесса перенаправления портов, поэтому единственный способ запустить DHCP-сервер внутри Docker - запустить контейнер как --net=host.

Вообще говоря, --net=hostон нужен только тогда, когда вы запускаете программы с очень специфическими, необычными сетевыми потребностями.

Наконец, с точки зрения безопасности, контейнеры Docker могут прослушивать множество портов, даже если они объявляют (раскрывают) только один порт. Обычно это нормально, поскольку вы перенаправляете только один ожидаемый порт, однако, если вы используете, --net=hostвы получите все порты контейнера, прослушивающие хост, даже те, которые не указаны в Dockerfile. Это означает, что вам нужно будет внимательно проверить контейнер (особенно, если он не ваш, например, официальный, предоставленный программным проектом), чтобы случайно не выставить дополнительные сервисы на машине.


Каким будет поведение, если несколько контейнеров будут запущены с параметрами --net = host? Будут ли запросы перенаправлены в случайный контейнер?
user482594

@ user482594: все они будут использовать один и тот же сетевой стек, как если бы вы запускали все программы в одном контейнере. например, если вы запускаете два веб-сервера, вам нужно убедиться, что они прослушивают разные порты, иначе второй контейнер получит сообщение об ошибке, что порт используется первым. Входящий трафик будет перенаправлен на тот контейнер, который его прослушивает (технически все --net=hostконтейнеры будут видеть трафик, но, конечно, только одна программа одновременно может прослушивать данный порт независимо от того, в каком контейнере вы ее запускаете, в этой настройке ).
Malvineous

1
  1. вы можете создать свою собственную новую сеть, например --net = "anyname"
  2. это сделано для того, чтобы изолировать сервисы от разных контейнеров.
  3. Предположим, что одна и та же служба работает в разных контейнерах, но отображение портов остается прежним, первый контейнер запускается нормально, но та же служба из второго контейнера не работает. поэтому, чтобы избежать этого, либо измените сопоставление портов, либо создайте сеть.

1
Спасибо за упоминание «2. Это сделано для изоляции (сетевых) сервисов от другого контейнера». Я действительно вижу ценность использования других конфигураций сети докеров (кроме host), если есть возможность запускать несколько контейнеров на одном хосте. В других случаях (когда изоляция сети не требуется) я бы предпочел --net=host.
CᴴᴀZ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.