Що насправді робить параметр --net = host у команді Docker?


90

Я трохи новачок у Docker. Я не міг знайти чіткого опису того, що ця опція робить у команді docker run, глибоко і трохи заплутаний у цьому.

Чи можемо ми використовувати його для доступу до програм, що працюють на контейнерах докерів, не вказавши порт? Як приклад, якщо я запускаю веб-програму, розгорнуту через образ докера в порту 8080, використовуючи опцію -p 8080:8080в команді docker run, я знаю, що мені доведеться отримати до неї доступ через порт 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

Я намагаюся це зробити просто. Отже, якщо запустити контейнер за замовчуванням, він буде створений усередині мережі bridge (docker0).

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

У dockerfile Дженкінса порти 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отримую доступ до свого сервера через порт, я отримую доступ до своїх дженкінів. Я думаю, що цей блог також корисний для його кращого розуміння.


4
Чи можна додати опцію --net=hostвсередині Dockerfile?
AnirbanDebnath

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

Так @AnirbanDebnath, це дозволено в Dockerfile. наприклад, у v3 - network_mode: "host"(ref - docs.docker.com/compose/compose-file/#network_mode )
Mohnish

Це файл Docker-Compose, який описує, як запустити контейнер. Не Dockerfile. Але справді, там можливо і робить те саме, що запустити докер --network = host
lvthillo

27

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

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

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

Наприклад, якщо ви хочете запустити DHCP-сервер, вам потрібно вміти слухати трансляцію трафіку в мережі та витягувати MAC-адресу з пакету. Ця інформація втрачається під час процесу переадресації портів, тому єдиним способом запуску DHCP-сервера всередині Docker є запуск контейнера як --net=host.

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

Нарешті, з точки зору безпеки, контейнери Docker можуть прослуховувати багато портів, хоча вони рекламують (виставляють) лише один порт. Зазвичай це нормально, оскільки ви пересилаєте лише один очікуваний порт, однак, якщо ви використовуєте, --net=hostто ви отримаєте всі порти контейнера, які прослуховуються на хості, навіть ті, які не перелічені у файлі Docker. Це означає, що вам потрібно буде уважно перевірити контейнер (особливо, якщо він не ваш, наприклад, офіційний, наданий проектом програмного забезпечення), щоб переконатися, що ви ненавмисно не виставляєте додаткові послуги на машині.


Якою буде поведінка, якщо кілька контейнерів запускаються з опціями '--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.