Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Поясніть роботу Docker networking. Які є типи мереж?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Docker має шість вбудованих мережевих драйверів**, кожен для іншого use case: `bridge` (дефолтний, single-host), `host` (без ізоляції), `none` (без мережі), `overlay` (multi-host через VXLAN), `macvlan` (container отримує MAC на фізичному LAN), `ipvlan` (схоже, на рівні IP). ```bash docker network ls # перелік мереж docker network create mynet # за замовчуванням створює user-defined bridge docker network create --driver overlay mynet # cross-host (Swarm) docker run --network mynet myapp # приєднати ``` **Головне:** для 95% single-host навантажень бери **user-defined bridge** (краща ізоляція + DNS, ніж дефолтний `bridge0`). Для multi-host бери `overlay`. `host` і `none` для спеціальних кейсів.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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. Корисно для дебагу проблем зі спілкуванням.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.