Docker Networking

Docker Networking

Docker Networking reprezintă infrastructura prin care containerele comunică între ele și cu lumea exterioară. Înțelegerea modelului de rețea Docker este esențială pentru proiectarea aplicațiilor containerizate sigure și scalabile.

Modelul de rețea Docker (CNM)

Docker folosește modelul Container Network Model (CNM), compus din trei abstracții fundamentale:

Componentă Descriere
Sandbox Mediu izolat de rețea al unui container (interfețe, tabele de rutare, DNS)
Endpoint Punct de conectare între un sandbox și o rețea
Network Grup de endpoint-uri care pot comunica direct între ele

Implementarea de referință a CNM este libnetwork, biblioteca Go folosită intern de Docker.

Tipuri de rețele Docker

1. Bridge (implicit)

Rețeaua de tip bridge este driverul implicit și cel mai frecvent utilizat. Docker creează automat o interfață virtuală docker0 pe host, care acționează ca un switch software.

Cum funcționează:

  • Fiecare container primește o interfață virtuală veth conectată la bridge
  • Containerele din același bridge pot comunica între ele prin IP
  • Traficul spre exterior trece prin NAT (masquerading)
  • Porturile se expun explicit cu -p

Bridge implicit vs. bridge definit de utilizator:

Caracteristică Bridge implicit (docker0) Bridge custom
Rezoluție DNS între containere ✗ Nu ✓ Da (prin nume)
Izolare automată ✗ Nu ✓ Da
Configurare flexibilă ✗ Limitată ✓ Completă
Recomandat pentru producție ✗ Nu ✓ Da
# Creare rețea bridge custom
docker network create --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  retea-app
 
# Pornire containere în rețeaua custom
docker run -d --name backend --network retea-app my-api
docker run -d --name frontend --network retea-app my-ui
 
# frontend poate accesa backend prin nume: http://backend:8080

2. Host

Driverul host elimină izolarea de rețea între container și host - containerul folosește direct stiva de rețea a mașinii gazdă.

Caracteristici:

  • Containerul partajează interfețele de rețea ale host-ului
  • Nu există NAT, nu sunt necesare mapări de porturi
  • Performanță maximă (fără overhead de rețea virtualizată)
  • Disponibil nativ doar pe Linux (pe macOS/Windows funcționează limitat)
# Rulare container în modul host
docker run -d --network host nginx
 
# nginx ascultă direct pe portul 80 al host-ului
# Nu este nevoie de -p 80:80
⚠ Atenție: Modul host reduce izolarea containerului. Folosiți-l doar când performanța rețelei este critică (ex: aplicații cu latență ultra-scăzută).

3. Overlay

Driverul overlay creează rețele distribuite care se întind pe mai multe noduri Docker (clustere Swarm sau Kubernetes cu plugin compatibil). Traficul este tunelat prin VXLAN.

Cerințe:

  • Docker Swarm inițializat (docker swarm init) sau un key-value store extern
  • Porturile 2377/tcp, 4789/udp, 7946/tcp+udp deschise între noduri

Cum funcționează:

  • Fiecare container primește un IP din subnet-ul overlay
  • Pachetele sunt încapsulate VXLAN și trimise prin rețeaua fizică
  • Un container de pe nodul A poate comunica cu unul de pe nodul B transparent
# Inițializare Swarm
docker swarm init --advertise-addr <IP-MANAGER>
 
# Creare rețea overlay
docker network create --driver overlay \
  --subnet 10.10.0.0/16 \
  retea-swarm
 
# Deployare servicii în rețeaua overlay
docker service create --name api \
  --network retea-swarm \
  --replicas 3 \
  my-api-image
 
docker service create --name db \
  --network retea-swarm \
  --replicas 1 \
  postgres:15

4. Macvlan

Driverul macvlan atribuie fiecărui container o adresă MAC unică, făcându-l să apară ca un dispozitiv fizic în rețea. Util pentru aplicații legacy care necesită conectivitate directă la rețeaua fizică.

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  retea-macvlan

5. None

Dezactivează complet rețeaua pentru un container. Util pentru procesare izolată (batch jobs, transformări de date fără acces la rețea).

docker run --network none alpine sh

Comunicarea între containere

Comunicare în același host (bridge)

┌─────────────────────────────────────────┐
│              Docker Host                │
│                                         │
│  ┌──────────┐       ┌──────────┐        │
│  │ container│       │ container│        │
│  │ frontend │       │ backend  │        │
│  │ 172.20.0.2│◄────►│172.20.0.3│        │
│  └────┬─────┘       └────┬─────┘        │
│       │                  │              │
│  ─────┴──────────────────┴─────         │
│         bridge: retea-app               │
│              172.20.0.1                 │
└─────────────────────────────────────────┘
  • Containerele din aceeași rețea bridge custom se descoperă prin nume (DNS intern Docker)
  • Nu este necesară expunerea porturilor (-p) pentru comunicare internă

Comunicare multi-host (overlay)

  Nod 1 (Manager)              Nod 2 (Worker)
┌──────────────────┐         ┌──────────────────┐
│  ┌────────────┐  │         │  ┌────────────┐  │
│  │  api       │  │         │  │  api       │  │
│  │ 10.10.0.2  │  │         │  │ 10.10.0.4  │  │
│  └─────┬──────┘  │         │  └─────┬──────┘  │
│        │ VXLAN   │◄───────►│        │ VXLAN   │
│  ┌─────┴──────┐  │  tunel  │  ┌─────┴──────┐  │
│  │  db        │  │         │  │  db        │  │
│  │ 10.10.0.3  │  │         │  │ 10.10.0.5  │  │
│  └────────────┘  │         │  └────────────┘  │
└──────────────────┘         └──────────────────┘
        └───────── overlay: retea-swarm ─────────┘

Conectare la rețele multiple

Un container poate fi conectat simultan la mai multe rețele, util pentru separarea traficului (ex: frontend ↔ backend ↔ baza de date):

docker network create retea-frontend
docker network create retea-backend
 
# Containerul "api" bridge între cele două rețele
docker run -d --name api \
  --network retea-frontend \
  my-api
 
docker network connect retea-backend api
 
# Acum "api" are acces la ambele rețele

Inspecție și depanare

# Lista rețelelor existente
docker network ls
 
# Inspecție detaliată a unei rețele
docker network inspect retea-app
 
# Verificare conectivitate între containere
docker exec frontend ping backend
 
# Vizualizare interfețe de rețea din container
docker exec frontend ip addr
 
# Urmărire rute
docker exec frontend ip route
 
# Eliminare rețele neutilizate
docker network prune

Porturi și expunere

Opțiune Sintaxă Descriere
Expunere completă -p 8080:80 Host:8080 → Container:80
Legare la interfață -p 127.0.0.1:8080:80 Doar localhost, nu extern
Port aleatoriu -p 80 Port aleatoriu pe host
UDP -p 5353:53/udp Protocol UDP explicit
EXPOSE (Dockerfile) EXPOSE 80 Documentație, nu mapare reală
💡 Bună practică: Legați porturile la 127.0.0.1 dacă serviciul nu trebuie să fie accesibil din exterior. Expunerea la 0.0.0.0 (implicit) poate crea riscuri de securitate.

DNS în Docker

Docker rulează un resolver DNS intern (127.0.0.11) disponibil în fiecare container:

  • Rețele bridge custom: rezoluție automată prin numele containerului sau alias
  • Swarm overlay: rezoluție prin numele serviciului (cu load balancing VIP)
  • Suportă DNS round-robin pentru scalare orizontală
# Adăugare alias DNS pentru un container
docker run -d --name cache \
  --network retea-app \
  --network-alias redis \
  redis:7
 
# Acum alte containere pot accesa cache-ul prin "redis" sau "cache"

Comparație rapidă a driverelor

Driver Izolare Multi-host Performanță Caz de utilizare
bridge Bună Dezvoltare, single-host
host Maximă Performanță critică (Linux)
overlay Bună Swarm, microservicii distribuite
macvlan Maximă Integrare rețea fizică, legacy
none Total N/A Izolare completă

Bune practici

  1. Folosiți întotdeauna rețele bridge custom în loc de rețeaua implicită docker0
  2. Segmentați rețelele pe straturi (frontend / backend / date) pentru principiul least-privilege
  3. Nu expuneți porturi interne dacă serviciile comunică doar intern
  4. Folosiți overlay pentru comunicare multi-host în loc de soluții manuale (SSH tunneling etc.)
  5. Numiți rețelele sugestiv (retea-prod-frontend) pentru management ușor
  6. Documentați subnet-urile alocate pentru a evita conflicte CIDR

Referințe