Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як troubleshoot мережеві проблеми між контейнерами?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Йди по stack-у top-down: **DNS → IP → ports → firewall**. ```bash # 1. Чи на тій самій мережі? docker inspect <container> --format '{{json .NetworkSettings.Networks}}' # 2. DNS працює? (лише на user-defined networks, не default bridge) docker exec app ping db docker exec app dig db # 3. Дотягається до IP напряму? docker exec app ping 172.18.0.3 # 4. Port відкритий? docker exec app nc -vz db 5432 # 5. Інспектуй bridge sudo iptables -L DOCKER-USER -nv sudo tcpdump -i docker0 ``` **Топ причин:** container'и на різних мережах, default bridge без DNS, host-firewall (UFW, firewalld) блокує bridge, MTU mismatch на overlay-мережах.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Network-troubleshooting** в Docker значить йти від DNS вниз до packet-інспекції, поки не знайдеш, де connection ламається. Більшість issue у верхніх трьох layer-ах (неправильна мережа, немає DNS, заблокований port). Тягнись до tcpdump і iptables лише, коли ці провалюються. ## Теорія ### TL;DR - Container'и доходять один до одного, лише якщо **на тій самій мережі**. - **Дефолтний `bridge` без DNS** між container'ами; user-defined bridge мають. - Host-firewall (UFW, firewalld, custom iptables) часто заважає docker0-bridge. - `--network=host` шарить host network-namespace; без isolation. - Overlay-мережі (Swarm) потребують UDP 4789 (VXLAN) і MTU нижчий за host. - Порядок діагностики: **layer-by-layer** від name-resolution вниз до packet'ів. ### Diagnostic checklist 1. **На якій мережі кожен container?** 2. **Чи DNS resolve'ить peer's name?** 3. **Чи peer's IP reachable (ping)?** 4. **Чи target-port відкритий (nc, telnet)?** 5. **Чи target-сервіс реально слухає на тому port і bind'иться до правильного interface?** 6. **Чи firewall (host або in-container) дропає packet?** 7. **Чи щось не так на layer 2/3 (MTU, MAC-address конфлікт)?** ### Типи мереж і їхні gotcha **Дефолтний `bridge` (без імені)** - Auto-присвоюється container'ам без `--network`. - **Без DNS між container'ами.** Імена не resolve'ляться. Треба `--link` (deprecated) або IP. - Уникай для всього, крім toy-use. **User-defined bridge** (`docker network create mynet`) - DNS працює: container'и доходять один до одного за container-ім'ям. - Isolated від default-bridge. - Дефолт для Compose-проєктів (один bridge per project). **`host`-мережа** (`--network=host`) - Container шарить host network-namespace. - Port-mapping не потрібен; без isolation. - Корисно для performance-sensitive випадків або system-tool. - Linux-only поведінка; на Docker Desktop (Mac/Windows) це **не** значить host-networking, значить host VM. **Overlay** (Swarm) - Простягається через кілька Docker-host через VXLAN. - Потребує UDP 4789 між host-ами для VXLAN-трафіку, TCP/UDP 7946 для control-plane. - MTU mismatch це класичний overlay-bug: VXLAN-encapsulation додає 50 bytes; якщо host-MTU 1500, container-MTU має бути ≤ 1450. **`none`** (`--network=none`) - Лише loopback. Використовується для sandbox. ## Приклади ### Крок 1: підтверди, що обидва container'и на тій самій мережі ```bash docker inspect app --format '{{json .NetworkSettings.Networks}}' | jq # { # "my-app-default": { # "IPAddress": "172.18.0.3", # "Aliases": ["app", "abc123"] # } # } docker inspect db --format '{{json .NetworkSettings.Networks}}' | jq # { # "some-other-network": { # "IPAddress": "172.19.0.5" # } # } ``` Різні мережі: з'єднай їх або перенеси один container. ```bash docker network connect my-app-default db # тепер db на обох мережах ``` ### Крок 2: DNS ```bash docker exec app sh -c 'getent hosts db' # 172.18.0.5 db ``` Якщо нічого не resolve'иться: ти ймовірно на default `bridge`. Перейди на user-defined-мережу. ```bash docker exec app cat /etc/resolv.conf # nameserver 127.0.0.11 ← embedded Docker-DNS ``` `127.0.0.11` це embedded resolver, який Docker injects у user-defined-мережі. Відсутність значить default-bridge issue. ### Крок 3: IP-рівень reachability ```bash docker exec app ping -c 3 db # PING db (172.18.0.5): 56 data bytes # 64 bytes from 172.18.0.5: seq=0 ttl=64 time=0.080 ms ``` Без відповіді: networking-layer зламаний. Перевір `iptables`: ```bash sudo iptables -L DOCKER-USER -nv sudo iptables -L DOCKER -nv ``` UFW часто скидає ці chain'и; додай explicit allow або вимкни UFW-втручання. ### Крок 4: port-рівень reachability ```bash docker exec app nc -vz db 5432 # Connection to db 5432 port [tcp/postgresql] succeeded! ``` `Connection refused`: сервіс не слухає на тому port. `Operation timed out`: firewall (host або in-container) дропає packet. ```bash # Всередині db-container docker exec db ss -tlnp # State Recv-Q Send-Q Local Address:Port # LISTEN 0 128 127.0.0.1:5432 ← bind на localhost, не на container-interface! ``` Класична помилка: Postgres bind на `127.0.0.1` замість `0.0.0.0` недосяжний з peer-container'ів. Фіксь сервіс-config: `listen_addresses = '*'` для Postgres. ### Крок 5: packet-capture (коли нічого інше не допомагає) Знайди ім'я bridge: ```bash docker network inspect my-app-default --format '{{.Id}}' # 4f7c9... (перші 12 chars стають суфіксом bridge-interface name) ip link show | grep br- # br-4f7c9... ``` Capture: ```bash sudo tcpdump -i br-4f7c9 -nn 'host 172.18.0.5 and port 5432' ``` Запусти запит з app, дивися flow-packet'ів. SYN без SYN-ACK = firewall drop або сервіс не слухає. Reset = сервіс відмовив. ### Крок 6: container-level firewall Деякі images shipping iptables-rules (security-hardened distro): ```bash docker exec db iptables -L -nv # Chain INPUT (policy DROP 0 packets, 0 bytes) ``` `policy DROP` блокує все, що явно не дозволено. Або фікс in-container-rules, або base-image без них. ### Типові сценарії і фікс #### «Не дотягається до db з app», Compose-проєкт ```yaml services: app: image: myorg/app db: image: postgres:16 ``` Compose auto-створює `<project>_default`-мережу. Обидва сервіси на ній. `app` дотягається до `db` за іменем. Має просто працювати. Якщо ламається: підтверди, що обидва піднялися (`docker compose ps`), потім: ```bash docker compose exec app ping db docker compose exec app nc -vz db 5432 ``` #### «Host не може дотягтися до published port container» ```bash docker run -d -p 8080:80 nginx curl localhost:8080 # працює curl 192.168.1.5:8080 # не працює з іншої машини ``` Перевір host-firewall: `ufw status`, `firewall-cmd --list-all`, або `iptables -L`. Відкрий port 8080. #### «Container може дотягтися до зовнішнього інтернету, але не до іншого container» Ймовірно на default `bridge` (без DNS) або на різних мережах. Перейди на user-defined bridge: ```bash docker network create mynet docker run --network=mynet --name=app myorg/app docker run --network=mynet --name=db postgres:16 ``` #### «Випадкові connection-drop або повільний Swarm-overlay» MTU mismatch. Перевір host-MTU: ```bash ip link show eth0 | grep mtu # mtu 1500 ``` VXLAN-overhead = 50 bytes. Container'и в overlay мають крутитися на MTU 1450 (або 1400 для безпеки через cloud-NAT). Set per-network: ```bash docker network create -d overlay \ --opt com.docker.network.driver.mtu=1450 \ swarm-net ``` #### «`--network=host` працює на Linux, fail на Mac» Docker Desktop крутить Linux у VM. `host`-networking таргетить VM, не твій Mac. Щоб дотягтися до `localhost` на Mac з container, бери `host.docker.internal`. ### Корисні tools - `nicolaka/netshoot`: debug-image з `dig`, `nc`, `tcpdump`, `iperf`, `mtr`, `tshark`. Запускай у тій самій мережі, що misbehaving container: ```bash docker run --rm -it --network=container:app nicolaka/netshoot # Тепер маєш повний diagnostic-toolkit у network-namespace app ``` - `docker logs <container>` для логу сервісу; часто failure на listening-стороні. - `docker exec <container> cat /etc/hosts`, щоб побачити, що container бачить як власне ім'я. ## Реальне застосування - **«App не дотягається до DB»**: 90% часу, мережі misaligned або DNS відсутній. Застосуй кроки 1-2. - **Intermittent-failure**: зазвичай MTU на overlay або DNS-TTL з restarting-container'ами. - **Production-outage**: tcpdump на bridge, потім iptables. Зроби packet-capture перед тим, як щось перезапускати. ### Типові помилки **Ставити сервіси на default-bridge** Без DNS. Завжди створюй user-defined-мережу або покладайся на Compose-auto-network. **Bind сервісу на `127.0.0.1` всередині container** Досяжно лише з того container. Bind на `0.0.0.0`, щоб інші container'и могли дотягтися через bridge. **Модифікація host-iptables вручну** Docker переписує iptables на кожному restart. Custom-rules належать у `DOCKER-USER`-chain (Docker його не чіпає). **Використання `--link`** Deprecated. Setup'ить `/etc/hosts`-entries, без DNS. Бери user-defined-мережі. ### Питання для поглиблення **Q:** Чому default-bridge без DNS? **A:** Історично. Default-bridge передує embedded Docker-DNS-server. User-defined-bridge додав DNS, але старий behavior зберегли для compatibility. **Q:** Що таке `127.0.0.11`? **A:** Embedded Docker DNS-resolver. Кожен container у user-defined-мережі має його як `nameserver`, і запити resolve'ляться у IP інших container'ів. **Q:** Як побачити, які packet'и дропаються на host-firewall? **A:** Додай logging-rule перед DROP-rule: `iptables -I DOCKER-USER -j LOG --log-prefix 'docker-drop: '`. Потім `dmesg -w` показує drop у real time. **Q:** (Senior) Як debug'ити overlay-мережу, що працює локально, але втрачає packet'и через host'и? **A:** Підтверди, що UDP 4789 (VXLAN) дозволений між host'ами (cloud-security-group часто блокує). Запусти `tcpdump -i any port 4789` на обох host'ах під час failing-request. Перевір MTU; знизь до 1400, якщо VXLAN йде через якийсь tunnel, що додає overhead. Інспектуй `docker network inspect <overlay>` для peer-counts; mismatched-peers значить Swarm-gossip нездоровий. **Q:** (Senior) Як детектити MAC-address конфлікти на custom-bridge? **A:** `docker network inspect <net>` перелічує MAC кожного container. Конфлікти приходять з manual `--mac-address`. Kernel логує `bridge: received packet on br0 with own address as source address` при конфліктах. Фікс через прибирання manual-MAC-assignment.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.