Коли ваші мікросервіси ростуть, виникає питання: як організувати мережеву взаємодію між контейнерами? На одному хості це просто, але що робити коли сервіси розподілені між кількома серверами? У цій статті розберемо все – від bridge networks до Docker Swarm та overlay networks.
Що ви дізнаєтесь:
- Типи Docker мереж та коли їх використовувати
- Як організувати мережі для мікросервісної архітектури
- Комунікація між контейнерами на різних хостах
- Практичні приклади з реальних проєктів
- Безпека та best practices
Час читання: 20-25 хвилин
Складність: Середній → Просунутий
Частина 1: Типи Docker мереж
1.1 Bridge Network (За замовчуванням)
Що це? Віртуальна мережа на одному хості. Контейнери можуть спілкуватися між собою через ім’я контейнера.
|
1 2 3 4 5 |
# docker-compose.yml networks: my-network: driver: bridge |
Приклад нашого проєкту:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
networks: parser-network: driver: bridge services: content-parser-dev: networks: - parser-network ai-database: networks: - parser-network ai-redis: networks: - parser-network |
Як це працює:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
┌─────────────────── HOST MACHINE ───────────────────┐ │ │ │ ┌─────────────── parser-network ───────────────┐ │ │ │ │ │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ │ │ content-parser │ │ ai-database │ │ │ │ │ │ 172.20.0.2:8080 │◄─┤ 172.20.0.3:5432 │ │ │ │ │ └──────────────────┘ └──────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────┐ │ │ │ │ │ ai-redis │ │ │ │ │ │ 172.20.0.4:6379 │ │ │ │ │ └──────────────────┘ │ │ │ └───────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘ |
Комунікація:
|
1 2 3 4 5 6 |
# З контейнера content-parser можна звертатись: curl http://ai-database:5432 curl http://ai-redis:6379 # Docker DNS автоматично резолвить імена |
Коли використовувати:
- ✅ Всі сервіси на одному хості
- ✅ Розробка та тестування
- ✅ Невеликі проєкти
Обмеження:
- ❌ Працює тільки на одному хості
- ❌ Не підходить для production з кількома серверами
1.2 External Network (Спільна мережа)
Що це? Мережа створена зовні docker-compose, до якої можуть підключатися різні stack’и.
Наш випадок:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Laravel проєкт (окремий docker-compose.yml) networks: shared_network: driver: bridge services: php83: networks: - shared_network nginx: networks: - shared_network |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Content Parser проєкт (окремий docker-compose.yml) networks: parser-network: driver: bridge shared_network: external: true # Підключаємось до існуючої name: shared_network services: content-parser-dev: networks: - parser-network # Внутрішня комунікація - shared_network # Комунікація з Laravel |
Як це працює:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
┌────────────────────── HOST MACHINE ───────────────────┐ │ │ │ ┌─────────── parser-network ──────────┐ │ │ │ │ │ │ │ ┌─────────────────┐ ┌──────────┐ │ │ │ │ │ content-parser │ │ database │ │ │ │ │ └────────┬────────┘ └──────────┘ │ │ │ └───────────┼─────────────────────────┘ │ │ │ │ │ ┌───────────┼──── shared_network ──────────────────┐ │ │ │ │ │ │ │ │ ┌────────▼────────┐ ┌─────────────────────┐ │ │ │ │ │ content-parser │ │ Laravel │ │ │ │ │ │ │◄─┤ (php83, nginx) │ │ │ │ │ └─────────────────┘ └─────────────────────┘ │ │ │ └──────────────────────────────────────────────────┘ │ └───────────────────────────────────────────────────────┘ |
Створення shared_network:
|
1 2 3 4 5 6 7 8 9 |
# Створити мережу вручну docker network create shared_network # Або в першому docker-compose.yml networks: shared_network: name: shared_network driver: bridge |
Комунікація між проєктами:
|
1 2 3 4 5 6 7 8 |
# З Laravel контейнера docker exec -it php83 bash curl http://content-parser-dev:8080/api/v1/health # З Content Parser docker exec -it content-parser-dev bash curl http://nginx:80 |
Коли використовувати:
- ✅ Кілька docker-compose проєктів на одному хості
- ✅ Мікросервісна архітектура
- ✅ Розділення concerns (frontend, backend, parser тощо)
1.3 Host Network
Що це? Контейнер використовує мережу хост машини напряму. Немає ізоляції.
|
1 2 3 4 |
services: app: network_mode: "host" |
Коли використовувати:
- ⚠️ Рідко! Тільки для специфічних випадків
- Моніторинг (Prometheus, node-exporter)
- Низька латентність (trading systems)
Недоліки:
- ❌ Немає ізоляції
- ❌ Конфлікти портів
- ❌ Погана переносимість
1.4 None Network
|
1 2 3 4 |
services: isolated-app: network_mode: "none" |
Коли використовувати:
- Batch jobs які не потребують мережі
- Максимальна ізоляція
Частина 2: Expose vs Ports
Різниця (критично для безпеки!)
|
1 2 3 4 5 6 |
# ❌ НЕБЕЗПЕЧНО для production services: api: ports: - "8080:8080" # Прокидує порт на хост |
Що відбувається:
- Порт 8080 доступний на
localhost:8080 - Порт 8080 доступний на
server-ip:8080 - Якщо сервер в інтернеті – порт доступний всім!
|
1 2 3 4 5 6 |
# ✅ БЕЗПЕЧНО для production services: api: expose: - "8080" # Тільки для Docker мережі |
Що відбувається:
- Порт 8080 доступний тільки іншим контейнерам
- НЕ доступний з хост машини
- НЕ доступний з інтернету
Наш приклад
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
services: # Production - без зовнішніх портів content-parser: profiles: ["prod"] expose: - "8080" networks: - shared_network # Development - з портом для зручності content-parser-dev: profiles: ["dev"] ports: - "8081:8080" # Тільки для розробки! networks: - shared_network |
Доступ:
|
1 2 3 4 5 6 7 8 9 |
# Production (тільки з інших контейнерів) docker exec -it php83 curl http://content-parser:8080 # Development (з хост машини) curl http://localhost:8081 # І з інших контейнерів docker exec -it php83 curl http://content-parser-dev:8080 |
Частина 3: Мультихост архітектура
Сценарій: Сервіси на різних серверах
|
1 2 3 4 5 |
┌─────── SERVER 1 ───────┐ ┌─────── SERVER 2 ──────┐ │ Laravel + Database │ │ Content Parser │ │ 172.16.0.100 │ │ 172.16.0.101 │ └────────────────────────┘ └────────────────────────┘ |
Проблема: Bridge networks працюють тільки на одному хості!
Рішення 1: Docker Swarm + Overlay Network
Docker Swarm – вбудований оркестратор. Overlay network створює віртуальну мережу між хостами.
Ініціалізація Swarm
|
1 2 3 4 5 6 7 8 9 |
# SERVER 1 (Manager) docker swarm init --advertise-addr 172.16.0.100 # Отримаєте токен для worker'ів: # docker swarm join --token SWMTKN-1-xxx 172.16.0.100:2377 # SERVER 2 (Worker) docker swarm join --token SWMTKN-1-xxx 172.16.0.100:2377 |
Створення Overlay Network
|
1 2 3 4 5 6 |
# На manager ноді docker network create \ --driver overlay \ --attachable \ multi-host-network |
Ключові параметри:
--driver overlay– мультихост мережа--attachable– можна підключати standalone контейнери
Docker Compose для Swarm
SERVER 1 (Laravel):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# docker-compose.yml services: php83: image: php:8.3-fpm networks: - multi-host-network nginx: image: nginx:alpine networks: - multi-host-network postgres: image: postgres:16 networks: - multi-host-network networks: multi-host-network: external: true |
SERVER 2 (Content Parser):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# docker-compose.yml services: content-parser: build: . networks: - multi-host-network redis: image: redis:7-alpine networks: - multi-host-network networks: multi-host-network: external: true |
Deployment
|
1 2 3 4 5 6 |
# На кожному сервері docker compose up -d # Або deploy як stack docker stack deploy -c docker-compose.yml myapp |
Комунікація
|
1 2 3 4 5 |
# З Laravel контейнера на SERVER 1 curl http://content-parser:8080 # Docker Swarm автоматично маршрутизує між хостами! |
Як це працює:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
┌────────────────────────────────────────────────────────┐ │ Overlay Network │ │ (multi-host-network) │ │ │ │ ┌─── SERVER 1 ────────────┐ ┌─── SERVER 2 ────────┐ │ │ │ │ │ │ │ │ │ ┌──────────────────┐ │ │ ┌────────────────┐ │ │ │ │ │ php83 │ │ │ │ content-parser │ │ │ │ │ │ 10.0.1.2 │◄──┼──┼──┤ 10.0.1.5 │ │ │ │ │ └──────────────────┘ │ │ └────────────────┘ │ │ │ │ │ │ │ │ │ │ ┌──────────────────┐ │ │ ┌────────────────┐ │ │ │ │ │ postgres │ │ │ │ redis │ │ │ │ │ │ 10.0.1.3 │ │ │ │ 10.0.1.6 │ │ │ │ │ └──────────────────┘ │ │ └────────────────┘ │ │ │ └──────────────────────────┘ └────────────────────┘ │ └────────────────────────────────────────────────────────┘ |
Переваги:
- ✅ Вбудовано в Docker
- ✅ Автоматичний DNS
- ✅ Encrypted комунікація
- ✅ Service discovery
Недоліки:
- ⚠️ Потребує Swarm mode
- ⚠️ Складніше налаштування
Рішення 2: Weave Net
Weave створює mesh мережу між хостами без Swarm.
|
1 2 3 4 5 6 7 8 9 10 |
# На кожному хості sudo curl -L git.io/weave -o /usr/local/bin/weave sudo chmod +x /usr/local/bin/weave # SERVER 1 weave launch # SERVER 2 (підключається до SERVER 1) weave launch 172.16.0.100 |
|
1 2 3 4 |
# Створюємо контейнери з Weave мережею eval $(weave env) docker compose up -d |
Рішення 3: VPN (WireGuard / Tailscale)
Найпростіше рішення – створити VPN між серверами.
Tailscale (найпростіше)
|
1 2 3 4 5 6 7 8 |
# На кожному сервері curl -fsSL https://tailscale.com/install.sh | sh tailscale up # Сервери тепер в одній мережі! # SERVER 1: 100.64.0.1 # SERVER 2: 100.64.0.2 |
|
1 2 3 4 5 6 7 |
# SERVER 2 - docker-compose.yml services: content-parser: environment: - DATABASE_URL=postgresql://user:pass@100.64.0.1:5432/db # Підключаємось до БД на SERVER 1 через Tailscale |
Переваги:
- ✅ Найпростіше налаштування
- ✅ Працює з існуючими docker-compose файлами
- ✅ Encrypted комунікація
- ✅ Не потребує Swarm
Недоліки:
- ❌ Використовує IP адреси (не DNS імена)
- ❌ Додатковий сервіс
Рішення 4: Consul + Registrator
Для складних мікросервісних архітектур.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Service Discovery з Consul services: consul: image: consul:latest ports: - "8500:8500" registrator: image: gliderlabs/registrator command: consul://consul:8500 volumes: - /var/run/docker.sock:/tmp/docker.sock |
Сервіси автоматично реєструються в Consul і можуть знаходити один одного.
Частина 4: Практичний приклад з нашого проєкту
Архітектура
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
┌────────────────────────────────────────────────────────┐ │ HOST MACHINE │ │ │ │ ┌────────────── Laravel Stack ─────────────┐ │ │ │ docker-compose.yml │ │ │ │ │ │ │ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ │ │ │ │ │ php83 │ │ nginx │ │postgres │ │ │ │ │ └────┬────┘ └────┬─────┘ └────┬────┘ │ │ │ │ │ │ │ │ │ │ │ └────────────┼─────────────┘ │ │ │ │ │ │ │ │ └────────────────────┼─────────────────────┘ │ │ │ │ │ shared_network│ │ │ ╔════════════════════╧═════════════════════╗ │ │ ║ ║ │ │ ║ ┌───────── Parser Stack ────────────┐ ║ │ │ ║ │ docker-compose.yml │ ║ │ │ ║ │ │ ║ │ │ ║ │ ┌────────────────┐ ┌─────────┐ │ ║ │ │ ║ │ │ content-parser │ │ redis │ │ ║ │ │ ║ │ └───────┬────────┘ └────┬────┘ │ ║ │ │ ║ │ │ │ │ ║ │ │ ║ │ └────────────────┘ │ ║ │ │ ║ │ │ ║ │ │ ║ │ ┌───────────────┐ │ ║ │ │ ║ │ │ ai-database │ │ ║ │ │ ║ │ └───────────────┘ │ ║ │ │ ║ │ │ ║ │ │ ║ └───────────────────────────────────┘ ║ │ │ ╚══════════════════════════════════════════╝ │ └────────────────────────────────────────────────────────┘ |
Laravel .env
|
1 2 3 |
CONTENT_PARSER_URL=http://content-parser-dev:8080 CONTENT_PARSER_SECRET=dev-parser-secret |
Content Parser docker-compose.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
services: content-parser-dev: profiles: ["dev"] build: context: . dockerfile: Dockerfile.dev container_name: content-parser-dev hostname: content-parser-dev ports: - "8081:8080" # Для доступу з хост машини networks: - parser-network # Внутрішня мережа (DB, Redis) - shared_network # Комунікація з Laravel environment: - DATABASE_URL=postgresql://user:pass@ai-database:5432/db?sslmode=disable - REDIS_URL=redis://ai-redis:6379/2 ai-database: image: postgres:16-alpine networks: - parser-network # Тільки parser-network! ai-redis: image: redis:7-alpine networks: - parser-network networks: parser-network: driver: bridge shared_network: external: true name: shared_network |
Чому parser-network окремо?
|
1 2 3 4 5 |
# ai-database НЕ в shared_network! ai-database: networks: - parser-network # ✅ Ізольована |
Причини:
- Безпека – Laravel не має прямого доступу до БД Parser’а
- Ізоляція – кожен сервіс контролює свою БД
- Separation of concerns – чітке розділення відповідальності
Комунікація:
|
1 2 3 4 5 6 |
Laravel → content-parser:8080 (shared_network) ✅ Laravel → ai-database:5432 ❌ (немає доступу) content-parser → ai-database:5432 (parser-network) ✅ content-parser → Laravel (shared_network) ✅ |
Частина 5: Безпека
5.1 Ports vs Expose
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# ❌ ПОГАНО - Production services: api: ports: - "8080:8080" # Доступний з інтернету! # ✅ ДОБРЕ - Production services: api: expose: - "8080" networks: - internal-network # Доступний тільки в Docker мережі |
5.2 Nginx як Reverse Proxy
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
services: nginx: ports: - "80:80" - "443:443" networks: - shared_network api: expose: - "8080" networks: - shared_network |
Nginx конфіг:
|
1 2 3 4 5 6 7 8 9 10 |
server { listen 80; server_name api.example.com; location / { proxy_pass http://api:8080; proxy_set_header Host $host; } } |
Тепер API доступний через Nginx, але порт 8080 закритий ззовні!
5.3 Firewall правила
|
1 2 3 4 5 6 7 8 9 10 |
# Дозволити тільки Docker мережі iptables -A INPUT -i docker0 -j ACCEPT iptables -A INPUT -p tcp --dport 8080 -j DROP # Для Swarm overlay iptables -A INPUT -p tcp --dport 2377 -j ACCEPT # Swarm management iptables -A INPUT -p tcp --dport 7946 -j ACCEPT # Container network discovery iptables -A INPUT -p udp --dport 7946 -j ACCEPT iptables -A INPUT -p udp --dport 4789 -j ACCEPT # Overlay network traffic |
5.4 Encrypted Communication
Docker Swarm (автоматично)
|
1 2 3 4 5 |
docker network create \ --driver overlay \ --opt encrypted \ # Включити шифрування secure-network |
Manual TLS
|
1 2 3 4 5 6 7 8 |
services: api: environment: - TLS_CERT=/certs/server.crt - TLS_KEY=/certs/server.key volumes: - ./certs:/certs:ro |
Частина 6: Troubleshooting
Проблема 1: Контейнери не бачать один одного
|
1 2 3 4 5 6 7 8 9 |
# Перевірити які мережі у контейнера docker inspect content-parser-dev | grep -A 10 Networks # Перевірити DNS docker exec content-parser-dev nslookup ai-database # Перевірити ping (якщо є ping в образі) docker exec content-parser-dev ping ai-database |
Рішення:
|
1 2 3 4 5 6 7 8 9 |
# Переконайтесь що обидва в одній мережі services: service1: networks: - shared_network service2: networks: - shared_network |
Проблема 2: “network not found”
|
1 2 3 4 5 6 |
# Перевірити існуючі мережі docker network ls # Створити якщо немає docker network create shared_network |
Проблема 3: “address already in use”
|
1 2 3 4 5 6 7 8 |
# Знайти що використовує порт lsof -i :8080 netstat -tulpn | grep 8080 # Або змінити порт ports: - "8081:8080" # Інший зовнішній порт |
Проблема 4: Swarm overlay не працює
|
1 2 3 4 5 6 7 8 9 10 |
# Перевірити статус Swarm docker info | grep Swarm # Перевірити які порти відкриті netstat -tulpn | grep -E "2377|7946|4789" # Переініціалізувати Swarm docker swarm leave --force docker swarm init |
Проблема 5: Повільна комунікація між хостами
|
1 2 3 4 5 6 7 8 9 |
# Перевірити MTU docker network inspect overlay-network | grep MTU # Зменшити MTU якщо проблеми docker network create \ --driver overlay \ --opt com.docker.network.driver.mtu=1450 \ overlay-network |
Частина 7: Best Practices
7.1 Naming Conventions
|
1 2 3 4 5 6 7 8 9 10 11 |
# ✅ ДОБРЕ - зрозумілі імена networks: backend-network: frontend-network: shared-network: # ❌ ПОГАНО networks: net1: net2: |
7.2 Network Segmentation
|
1 2 3 4 5 6 7 |
# Розділити на логічні групи networks: frontend: # nginx, React backend: # API servers database: # Databases cache: # Redis, Memcached |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
services: nginx: networks: - frontend api: networks: - frontend - backend postgres: networks: - backend # Тільки backend! |
7.3 Use Labels
|
1 2 3 4 5 6 7 |
networks: backend: labels: - "com.example.description=Backend services network" - "com.example.department=engineering" - "com.example.environment=production" |
7.4 Monitoring
|
1 2 3 4 5 6 7 8 9 10 11 |
# Prometheus для моніторингу мереж services: prometheus: image: prom/prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml command: - '--config.file=/etc/prometheus/prometheus.yml' networks: - monitoring |
7.5 Documentation
Завжди документуйте вашу мережеву архітектуру:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# docker-compose.yml # NETWORK ARCHITECTURE: # # frontend-network: # - nginx (port 80, 443) # - React app (port 3000) # # backend-network: # - API servers (port 8080) # - Database (port 5432) # # shared-network (external): # - Connects to Laravel stack # - Used for inter-service communication networks: frontend-network: backend-network: shared-network: external: true |
Частина 8: Скрипт для управління
Створимо bash скрипт для зручного управління мережами:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#!/bin/bash # network-manager.sh show_networks() { echo "=== Docker Networks ===" docker network ls --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}" } inspect_network() { NETWORK=$1 echo "=== Network: $NETWORK ===" docker network inspect $NETWORK | jq -r '.[0] | { Name: .Name, Driver: .Driver, Containers: [.Containers | to_entries[] | { name: .value.Name, ipv4: .value.IPv4Address }] }' } test_connectivity() { FROM_CONTAINER=$1 TO_CONTAINER=$2 echo "Testing: $FROM_CONTAINER → $TO_CONTAINER" docker exec $FROM_CONTAINER ping -c 1 $TO_CONTAINER && \ echo "✅ Connection successful" || \ echo "❌ Connection failed" } create_shared_network() { echo "Creating shared_network..." docker network create shared_network && \ echo "✅ Network created" || \ echo "⚠️ Network already exists" } cleanup_unused() { echo "Cleaning up unused networks..." docker network prune -f echo "✅ Cleanup complete" } case "${1:-help}" in list) show_networks ;; inspect) inspect_network ${2:-shared_network} ;; test) test_connectivity $2 $3 ;; create) create_shared_network ;; cleanup) cleanup_unused ;; *) echo "Usage: ./network-manager.sh [list|inspect|test|create|cleanup]" ;; esac |
Використання:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
chmod +x network-manager.sh # Список мереж ./network-manager.sh list # Перевірити мережу ./network-manager.sh inspect shared_network # Тест з'єднання ./network-manager.sh test php83 content-parser-dev # Створити shared мережу ./network-manager.sh create # Очистити невикористані мережі ./network-manager.sh cleanup |
Частина 9: Real-World Scenarios
Scenario 1: Microservices на одному хості
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# Структура: # - API Gateway (порт 80) # - Auth Service (internal) # - User Service (internal) # - Payment Service (internal) # - Database (internal) # - Redis (internal) services: api-gateway: ports: - "80:80" networks: - frontend - backend auth-service: expose: - "8081" networks: - backend user-service: expose: - "8082" networks: - backend payment-service: expose: - "8083" networks: - backend postgres: expose: - "5432" networks: - backend redis: expose: - "6379" networks: - backend networks: frontend: driver: bridge backend: driver: bridge |
Переваги:
- Тільки API Gateway доступний ззовні
- Всі інші сервіси захищені
- Проста архітектура
Scenario 2: Hybrid – частина на хості, частина в cloud
|
1 2 3 4 5 6 7 |
┌────── LOCAL HOST ─────┐ ┌────── CLOUD SERVER ─────┐ │ │ │ │ │ Laravel + Frontend │ │ Content Parser │ │ (Development) │─────────│ AI Services │ │ │ VPN/SSH │ (Production) │ └───────────────────────┘ └─────────────────────────┘ |
Налаштування з SSH тунелем:
|
1 2 3 4 5 6 |
# На локальній машині ssh -L 8080:localhost:8080 user@cloud-server # Тепер можна звертатись curl http://localhost:8080/api/v1/health |
Налаштування з Tailscale:
|
1 2 3 4 5 6 |
# На обох машинах tailscale up # LOCAL: 100.64.0.1 # CLOUD: 100.64.0.2 |
|
1 2 3 4 5 6 |
# docker-compose.yml на локальній машині services: laravel: environment: - CONTENT_PARSER_URL=http://100.64.0.2:8080 |
Scenario 3: Multi-region deployment
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
┌──────── EU Region ────────┐ ┌──────── US Region ────────┐ │ User Service (EU) │ │ User Service (US) │ │ Payment Service (EU) │ │ Payment Service (US) │ └───────────┬───────────────┘ └───────────┬───────────────┘ │ │ └────────────┬───────────────────┘ │ ┌────────▼─────────┐ │ Global Services │ │ - Auth │ │ - Analytics │ └──────────────────┘ |
Docker Swarm з constraints:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# docker-compose.yml version: '3.8' services: user-service-eu: image: user-service deploy: placement: constraints: - node.labels.region == eu networks: - global-network user-service-us: image: user-service deploy: placement: constraints: - node.labels.region == us networks: - global-network auth-service: image: auth-service deploy: replicas: 3 networks: - global-network networks: global-network: driver: overlay |
Позначити ноди:
|
1 2 3 4 5 6 7 8 |
# EU nodes docker node update --label-add region=eu node1 docker node update --label-add region=eu node2 # US nodes docker node update --label-add region=us node3 docker node update --label-add region=us node4 |
Scenario 4: Development → Staging → Production
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# .env.development NETWORK_SUFFIX=dev EXTERNAL_PORT=8081 # .env.staging NETWORK_SUFFIX=staging EXTERNAL_PORT=8082 # .env.production NETWORK_SUFFIX=prod EXTERNAL_PORT= # Немає зовнішніх портів! |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# docker-compose.yml services: api: image: api:${VERSION:-latest} ports: - "${EXTERNAL_PORT:-}:8080" # Порожнє = не відкривати expose: - "8080" networks: - app-network-${NETWORK_SUFFIX:-dev} networks: app-network-${NETWORK_SUFFIX:-dev}: name: app-network-${NETWORK_SUFFIX:-dev} |
Запуск:
|
1 2 3 4 5 6 |
# Development docker compose --env-file .env.development up # Production docker compose --env-file .env.production up |
Частина 10: Performance Optimization
10.1 MTU Settings
|
1 2 3 4 5 6 7 8 9 |
# Перевірити поточний MTU docker network inspect bridge | grep MTU # Створити мережу з оптимальним MTU docker network create \ --driver bridge \ --opt com.docker.network.driver.mtu=1450 \ optimized-network |
Коли змінювати MTU:
- VPN з’єднання (зменшити на 50-100)
- Jumbo frames (збільшити до 9000)
- Cloud providers (AWS, GCP мають рекомендації)
10.2 DNS Caching
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# docker-compose.yml services: dnsmasq: image: andyshinn/dnsmasq cap_add: - NET_ADMIN command: --cache-size=1000 app: dns: - dnsmasq |
10.3 Connection Pooling
|
1 2 3 4 5 6 |
// Приклад для Go db, err := sql.Open("postgres", databaseURL) db.SetMaxOpenConns(25) // Максимум з'єднань db.SetMaxIdleConns(5) // Idle з'єднання db.SetConnMaxLifetime(5 * time.Minute) |
10.4 Load Balancing
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# Nginx для балансування services: nginx: image: nginx volumes: - ./nginx.conf:/etc/nginx/nginx.conf ports: - "80:80" networks: - frontend api-1: image: api networks: - frontend api-2: image: api networks: - frontend api-3: image: api networks: - frontend |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# nginx.conf upstream api_backend { least_conn; # Алгоритм балансування server api-1:8080; server api-2:8080; server api-3:8080; } server { listen 80; location / { proxy_pass http://api_backend; } } |
Частина 11: Monitoring & Debugging
11.1 Network Traffic
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# Встановити tcpdump в контейнер docker exec -it content-parser-dev sh -c "apk add tcpdump" # Перехопити трафік docker exec content-parser-dev tcpdump -i eth0 port 8080 -w /tmp/capture.pcap # Скопіювати на хост docker cp content-parser-dev:/tmp/capture.pcap ./ # Аналізувати в Wireshark wireshark capture.pcap |
11.2 Prometheus Metrics
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# docker-compose.yml services: prometheus: image: prom/prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090" networks: - monitoring cadvisor: image: gcr.io/cadvisor/cadvisor volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro networks: - monitoring |
|
1 2 3 4 5 6 |
# prometheus.yml scrape_configs: - job_name: 'cadvisor' static_configs: - targets: ['cadvisor:8080'] |
11.3 Grafana Dashboard
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
services: grafana: image: grafana/grafana ports: - "3000:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=admin volumes: - grafana-storage:/var/lib/grafana networks: - monitoring volumes: grafana-storage: |
Метрики для моніторингу:
- Network throughput (MB/s)
- Latency між контейнерами
- Packet loss
- Connection count
- DNS resolution time
11.4 Logging
|
1 2 3 4 5 6 7 8 9 10 |
services: app: logging: driver: "json-file" options: max-size: "10m" max-file: "3" labels: "production_status" env: "os,customer" |
Централізований logging:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
services: loki: image: grafana/loki ports: - "3100:3100" promtail: image: grafana/promtail volumes: - /var/log:/var/log - ./promtail-config.yml:/etc/promtail/config.yml |
Частина 12: Security Deep Dive
12.1 Network Policies (з Kubernetes)
Якщо використовуєте Kubernetes замість Docker Compose:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: api-network-policy spec: podSelector: matchLabels: app: api policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080 egress: - to: - podSelector: matchLabels: app: database ports: - protocol: TCP port: 5432 |
12.2 Docker Security Scanner
|
1 2 3 4 5 6 |
# Сканування образів docker scan content-parser:latest # Сканування з Trivy trivy image content-parser:latest |
12.3 Secrets Management
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# docker-compose.yml services: api: secrets: - db_password - api_key environment: - DB_PASSWORD_FILE=/run/secrets/db_password secrets: db_password: file: ./secrets/db_password.txt api_key: external: true |
12.4 Read-only Root Filesystem
|
1 2 3 4 5 6 7 8 9 |
services: api: read_only: true tmpfs: - /tmp - /var/run security_opt: - no-new-privileges:true |
Частина 13: Migration Strategies
З bridge на overlay
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 1. Backup конфігурації docker inspect content-parser > backup-config.json # 2. Створити overlay мережу docker network create --driver overlay new-overlay-network # 3. Оновити docker-compose.yml services: app: networks: - new-overlay-network # 4. Graceful migration docker compose up -d --no-deps --scale app=2 # Запустити нову версію # Тестування docker compose up -d --no-deps --scale app=1 # Видалити стару версію |
Zero-downtime migration
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# docker-compose.yml services: app-blue: # Стара версія image: app:v1 networks: - old-network app-green: # Нова версія image: app:v2 networks: - new-network nginx: # Load balancer depends_on: - app-blue - app-green |
|
1 2 3 4 5 6 |
# nginx.conf - поступово перемикаємо трафік upstream backend { server app-blue:8080 weight=90; server app-green:8080 weight=10; } |
Частина 14: Advanced Topics
14.1 IPAM (IP Address Management)
|
1 2 3 4 5 6 7 8 9 10 |
networks: custom-network: driver: bridge ipam: driver: default config: - subnet: 172.28.0.0/16 gateway: 172.28.0.1 ip_range: 172.28.5.0/24 |
|
1 2 3 4 5 6 |
services: app: networks: custom-network: ipv4_address: 172.28.5.10 # Статична IP |
14.2 IPv6 Support
|
1 2 3 4 5 6 7 8 |
networks: ipv6-network: driver: bridge enable_ipv6: true ipam: config: - subnet: 2001:db8:1::/64 |
14.3 MacVLAN Networks
Контейнери отримують IP з фізичної мережі:
|
1 2 3 4 5 6 7 8 9 10 |
networks: macvlan-network: driver: macvlan driver_opts: parent: eth0 ipam: config: - subnet: 192.168.1.0/24 gateway: 192.168.1.1 |
Use cases:
- Legacy додатки що очікують physical network
- Network monitoring tools
- DHCP servers в контейнерах
14.4 Custom DNS
|
1 2 3 4 5 6 7 8 9 10 |
services: app: dns: - 8.8.8.8 - 8.8.4.4 dns_search: - example.com dns_opt: - ndots:5 |
Частина 15: Checklist для Production
Pre-deployment Checklist
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
## Network Configuration - [ ] Використовується `expose` замість `ports` для internal services - [ ] Налаштовано firewall правила - [ ] Overlay network для мультихост (якщо потрібно) - [ ] DNS правильно налаштований - [ ] SSL/TLS для зовнішніх з'єднань ## Security - [ ] No hardcoded passwords в docker-compose.yml - [ ] Secrets management налаштовано - [ ] Network segmentation впроваджено - [ ] Least privilege principle - [ ] Security scanning виконано ## Monitoring - [ ] Prometheus metrics exposed - [ ] Logging централізовано - [ ] Alerts налаштовано - [ ] Health checks працюють - [ ] Dashboard створено ## Performance - [ ] MTU оптимізовано - [ ] Connection pooling налаштовано - [ ] DNS caching - [ ] Load balancing (якщо потрібно) ## Disaster Recovery - [ ] Backup strategy - [ ] Rollback plan - [ ] Documentation оновлено - [ ] Team проінформовано |
Висновки
Що ми навчились
- Bridge Networks – для single-host розробки
- External Networks – для комунікації між docker-compose стеками
- Overlay Networks – для мультихост продакшн
- Expose vs Ports – критично для безпеки
- Network Segmentation – для ізоляції сервісів
Рекомендації
Для Development:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
networks: shared_network: external: true name: shared_network services: app: ports: - "8081:8080" # OK для dev networks: - shared_network |
Для Production:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
networks: app-network: driver: overlay encrypted: true services: app: expose: - "8080" # БЕЗ ports! networks: - app-network nginx: ports: - "443:443" # Тільки reverse proxy networks: - app-network |
Ключові принципи
- Least Privilege – мінімально необхідний доступ
- Defense in Depth – кілька рівнів безпеки
- Separation of Concerns – чітке розділення мереж
- Monitor Everything – якщо не моніторите, не контролюєте
- Document Always – майбутній ви подякує
Корисні ресурси
Бонус: Quick Reference Commands
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# === Мережі === docker network ls # Список мереж docker network inspect NETWORK # Деталі мережі docker network create NETWORK # Створити мережу docker network rm NETWORK # Видалити мережу docker network prune # Видалити невикористані docker network connect NETWORK CONTAINER # Підключити контейнер docker network disconnect NETWORK CONTAINER # Відключити контейнер # === Debugging === docker exec CONTAINER ip addr # IP адреси docker exec CONTAINER ping OTHER # Тест connectivity docker exec CONTAINER nslookup OTHER # DNS lookup docker exec CONTAINER netstat -tulpn # Відкриті порти docker exec CONTAINER route -n # Routing table # === Swarm === docker swarm init # Ініціалізація Swarm docker swarm join-token worker # Отримати токен docker node ls # Список нод docker service create # Створити сервіс docker service ls # Список сервісів docker stack deploy -c file.yml STACK # Deploy stack # === Моніторинг === docker stats # Ресурси контейнерів docker top CONTAINER # Процеси в контейнері docker logs -f CONTAINER # Логи (follow) docker events # Docker events |
Що далі?
У наступних постах у цьому розділі:
- Kubernetes Networking – для enterprise scale
- Service Mesh (Istio, Linkerd) – для складних мікросервісів
- eBPF – для network observability
- Cilium – modern networking для Kubernetes
Happy Networking! 🚀
Якщо у вас є питання або доповнення – пишіть в коментарях!