Skip to main content

Поясніть роботу Docker networking. Які є типи мереж?

Docker networking це шар, що вирішує, як container дістають один одного і зовнішній світ. Шість вбудованих драйверів, але більшість прод-сетапів використовує лише два: user-defined bridge для single host, overlay для multi-host.

Теорія

TL;DR

  • Docker створює віртуальні мережі; container приєднуються і отримують внутрішній IP.
  • Шість вбудованих драйверів покривають кожен поширений кейс. Обирай за топологією, не за вподобанням.
  • bridge (дефолт): ізольована віртуальна мережа на одному host. Дефолт для docker run, якщо не задаєш.
  • User-defined bridge як дефолтний bridge, але з DNS-резолюцією по імені container, майже завжди кращий вибір.
  • host: container ділить network stack host (без ізоляції, найшвидше).
  • none: жодної мережі (рідко, для дуже locked-down навантажень).
  • overlay: охоплює кілька Docker host через VXLAN. Потрібен для Swarm-сервісів.
  • macvlan / ipvlan: container з'являється як реальний пристрій на фізичному LAN (рідко, для legacy або специфічних маршрутизаційних потреб).

Швидкий приклад

bash
# Перелік мереж, що Docker створює за замовчуванням $ docker network ls NETWORK ID NAME DRIVER SCOPE 4f06b3e2c0c1 bridge bridge local 8a3f2d1c9b8e host host local 1234567890ab none null local # Створимо user-defined bridge (правильний дефолт для app-стеків) $ docker network create mynet # Запустимо два container; вони можуть ping'ати одне одного по імені $ docker run -d --name api --network mynet myapp $ docker run -d --name db --network mynet postgres:16 $ docker exec api ping -c 1 db # Резолвить db → 172.18.0.2 через embedded DNS Docker, ICMP працює.

User-defined bridge дають name-based DNS автоматично, дефолтний bridge ні. Це сама причина брати їх.

Драйвери детально

bridge (дефолт) — single host

Віртуальний L2-bridge на host. Container, приєднані до нього, отримують IP на приватному підмережі (наприклад, 172.17.0.0/16 для дефолтного bridge).

  • Дефолтна bridge-мережа (створена Docker при інсталі): без DNS по імені, лише через --link (deprecated). Уникай.
  • User-defined bridge (docker network create mynet): container резолвлять одне одного по імені container. Завжди краще.

Iptables NAT-правила форвардять опубліковані порти (-p) з host на IP container.

host — без ізоляції

bash
docker run --network host nginx # nginx слухає host-порт 80 напряму. -p не треба.

Container ділить network namespace host. Без NAT, без port mapping, без окремого IP. По продуктивності найшвидше (без overhead). По безпеці найслабше (container бачить кожен host-інтерфейс).

Бери, коли треба сирий мережевий performance або bind на конкретні host-інтерфейси. Уникай у shared / multi-tenant сетапах.

none — ізольовано

bash
docker run --network none alpine ip a # Лише loopback (lo). Жодної зовнішньої мережі.

Container має свій network namespace, але немає інтерфейсів крім lo. Бери для batch-job, що не повинні чіпати мережу, або для ручного налаштування мережі post-factum.

overlay — multi-host (Swarm)

Охоплює Docker-host у Swarm-кластері через VXLAN-енкапсуляцію. Container на host A і host B можуть говорити, ніби на тому самому LAN.

bash
# На Swarm-менеджері $ docker network create --driver overlay --attachable myoverlay

Використовується для Swarm-сервісів. Без Swarm майже ніколи не тягнешся за overlay. Kubernetes має свій еквівалент (CNI-плагіни) і не використовує Docker overlay.

macvlan — container як реальний пристрій на LAN

Container отримує свою MAC-адресу на фізичній мережі. Виглядає як окремий пристрій для роутера, DHCP-сервера тощо.

bash
$ docker network create --driver macvlan \ --subnet=192.168.1.0/24 \ --gateway=192.168.1.1 \ -o parent=eth0 \ pubnet $ docker run --network pubnet --ip 192.168.1.50 myapp

Бери, коли legacy-софт очікує bind на реальний LAN-інтерфейс, або коли треба, щоб кожен container був на тій самій підмережі, що й офісна. Caveat: більшість cloud-провайдерів (AWS, GCP, Azure) блокують MAC, які не присвоїли, macvlan чисто не працює у хмарі.

ipvlan — схоже на macvlan, IP-рівень

Як macvlan, але container ділять MAC host. Краще для середовищ, де MAC обмежені (хмара, switch port-security). Менш поширений, ніж macvlan.

Як працює DNS container

User-defined bridge і overlay-мережі включають embedded DNS-сервер Docker на 127.0.0.11. З container:

bash
# Container 'api' на 'mynet' резолвить сусіда 'db' $ docker exec api cat /etc/resolv.conf nameserver 127.0.0.11 $ docker exec api nslookup db Server: 127.0.0.11 Name: db Address 1: 172.18.0.2

DNS знає про усі container на тій самій мережі. Імена резолвляться у поточні IP (IP container можуть мінятися на рестарті, DNS встигає).

Команди управління мережею

bash
docker network ls # перелік docker network inspect <name> # повні деталі (subnet, приєднані container) docker network create [opts] <name> # створити docker network rm <name> # видалити (має бути порожнім) docker network connect <net> <container> # приєднати running container docker network disconnect <net> <container> # відключити docker network prune # видалити невикористані

Типові помилки

Використання дефолтного bridge і дивуватися, чому DNS падає

bash
# НЕПРАВИЛЬНО: container на дефолтному bridge не резолвлять одне одного по імені $ docker run -d --name db postgres:16 $ docker run -d --name api myapp # обидва на дефолтному bridge $ docker exec api ping db # name resolution падає

Фікс: створи user-defined bridge.

bash
$ docker network create mynet $ docker run -d --name db --network mynet postgres:16 $ docker run -d --name api --network mynet myapp $ docker exec api ping db # працює

Compose створює user-defined bridge per project автоматично, тому DNS «просто працює» у Compose.

Публікація портів на host-мережі

bash
# НЕПРАВИЛЬНО: -p ігнорується на host-мережі $ docker run --network host -p 8080:80 nginx # nginx все одно слухає host:80 (його реальний порт), -p нічого не робить

host-режим і -p взаємно виключні. Обирай одне.

Використання localhost для з'єднання з іншими container

Класична помилка. localhost всередині container це сам container. Бери service-ім'я (на user-defined bridge або Compose-проекті) або IP container (крихко, IP міняються).

Overlay без Swarm

bash
$ docker network create --driver overlay test Error response from daemon: This node is not a swarm manager.

Overlay потребує Swarm-кластер (docker swarm init спочатку). Поза Swarm бери bridge.

Реальне застосування

  • Локальний dev з Compose: кожен project автоматично отримує свій user-defined bridge. Service-name DNS працює з коробки.
  • Single-host production: явний user-defined bridge на app-стек. Внутрішні сервіси без публікації, web/proxy опубліковано.
  • Swarm-кластери: overlay-мережі для service-to-service трафіку між node. Шифровано за замовчуванням у сучасному Swarm.
  • Performance-критичні навантаження на bare metal: --network host, щоб скіпнути bridge і NAT-overhead.
  • Спеціальна LAN-інтеграція (legacy, IoT, домашні лаби): macvlan, щоб container були «на LAN» зі своїм IP/MAC.

Питання для поглиблення

Q: Чому container на user-defined bridge мають DNS, а на дефолтному bridge ні?


A: Історично. Дефолтна bridge-мережа це оригінальна реалізація Docker; user-defined bridge прийшли пізніше з DNS-by-name з коробки. Дефолтний bridge зберегли для backward-compatibility, але по суті deprecated для нових use case.

Q: Чи може container належати кільком мережам?


A: Так. docker run --network net1 ... && docker network connect net2 container. Корисно для розділення відповідальностей: web container на frontend і backend, db лише на backend.

Q: Яка різниця між bridge і --network=host?


A: bridge дає container свій network namespace і IP, з NAT, що транслює до/від host. host робить, щоб container ділив network namespace host, той самий IP, ті самі інтерфейси, без NAT.

Q: Як Kubernetes networking співвідноситься з Docker?


A: Kubernetes не використовує Docker networking. K8s має CNI (Container Network Interface) plugin-модель, кожен pod отримує свій network namespace, але connectivity забезпечує CNI-плагін (Calico, Flannel, Cilium тощо), не Docker. Під капотом runtime (containerd) все ще створює namespace; Kubernetes дає IP і routing.

Q: (Senior) Коли б ти обрав macvlan замість bridge з -p?


A: Коли трафік container має походити з реальної LAN-адреси (legacy-сервіси, що whitelist'ять по IP, license-сервери, прив'язані до MAC, мережеве обладнання). Bridge + -p завжди показує IP host ззовні; macvlan дає container свій IP. Уникай у хмарі, великі cloud-провайдери відхиляють незнайомі MAC на hypervisor.

Приклади

Ручне створення user-defined bridge для стеку

bash
$ docker network create --driver bridge \ --subnet 172.20.0.0/24 \ --gateway 172.20.0.1 \ appnet $ docker run -d --name db --network appnet \ -e POSTGRES_PASSWORD=devpass postgres:16 $ docker run -d --name api --network appnet \ -e DATABASE_URL=postgres://postgres:devpass@db:5432/app myapp $ docker run -d --name web --network appnet -p 80:80 nginx # web дістає api по імені; api дістає db по імені; лише web відкритий host.

Production-shape патерн: явна мережа, сервіси без публікації крім entry point.

Inspecting мережі

bash
$ docker network inspect appnet --format '{{json .Containers}}' | jq { "a3f9d2b8c1e4": { "Name": "db", "IPv4Address": "172.20.0.2/24" }, "b7e1f4d6a2b8": { "Name": "api", "IPv4Address": "172.20.0.3/24" }, ... }

Хто на мережі і з яким IP. Корисно для дебагу проблем зі спілкуванням.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Коментарі

Ще немає коментарів