Skip to main content
  1. Concetti/

Docker Network

·6 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

Cosa fa
#

Docker crea reti virtuali isolate tra i container. Ogni rete e' come un palazzo separato — i container dentro si vedono tra loro, quelli fuori non esistono. Il DNS interno risolve i nomi dei container automaticamente.

TL;DR
#

# Senza reti esplicite: ogni compose crea la sua rete isolata
# I container di compose diversi non si parlano

# Con reti condivise: i container si trovano per nome
n8n  ────► postgres  (stessa rete "internal")
           └── n8n raggiunge postgres con hostname "postgres"

# Traefik vede solo i container sulla rete "web"
browser ──► traefik ──► app      (rete web)
                   NON vede postgres  (solo rete internal)

Le reti Docker replicano la segmentazione di rete: ogni servizio e' esposto solo a chi deve vederlo.


Analogia — il condominio con citofoni
#

Condominio A (rete internal):          Condominio B (rete web):
  postgres  ←→  redis                    traefik  ←→  rails
  rails     ←→  postgres

rails sta in ENTRAMBI i condomini — ha due citofoni.
postgres sta solo nel condominio A — dall'esterno non lo raggiungi.

Tipi di rete
#

graph TD
    subgraph Host fisico
        subgraph BridgeDefault["bridge default - docker0 - 172.17.0.x"]
            A[Container A]
            B[Container B]
            A <-->|IP fisso| B
        end
        subgraph BridgeCustom["bridge custom - mynetwork"]
            C[Traefik]
            D[Chatwoot]
            C <-->|nome container| D
        end
        subgraph HostNet["host - nessun isolamento"]
            E[Container E]
        end
        BridgeDefault -->|NAT| eth0
        BridgeCustom -->|porta esposta| eth0
        HostNet -->|accesso diretto| eth0
    end
    eth0 --> Internet
TipoIsolamentoDNS internoQuando usare
bridge defaultParzialeNo — solo IPTest rapidi
bridge customCompletoSi — per nomeProduzione
hostNessunoN/APerformance massima
noneTotaleN/AContainer completamente isolato

DNS interno Docker
#

Nelle reti bridge custom, Docker avvia un DNS interno. I container si raggiungono per nome — non per IP:

# Rete default — devi conoscere l'IP (cambia ad ogni riavvio)
ping 172.17.0.3   # fragile

# Rete custom — usi il nome del servizio docker-compose
ping postgres     # stabile, sempre funziona
ping redis
ping chatwoot

Questo e' il motivo per cui nel docker-compose si scrive:

# .env
DATABASE_URL=postgresql://user:pass@postgres:5432/chatwoot
#                                    ^^^^^^^^
#                                    nome del container — non IP
REDIS_URL=redis://redis:6379

Owned vs External
#

Ogni rete ha un compose che la possiede (la crea) e altri che la usano.

# Chi CREA la rete (proprietario)
# traefik/docker-compose.yml
networks:
  web:
    name: web       # nome fisico fisso su Docker

# Chi USA la rete (tutti gli altri)
# n8n/docker-compose.yml
networks:
  web:
    external: true  # "non crearla, cercala gia esistente"
    name: web

Il proprietario naturale di una rete e' il servizio che:

  • vive piu' a lungo degli altri
  • e' il primo ad avviarsi
  • e' l'ultimo a spegnersi

Nome fisso con name:
#

Senza name:, Docker usa il prefisso della cartella del compose:

cartella: infra/traefik/
rete dichiarata: web
risultato: traefik_web    ← dipende dalla cartella

Con name: web il nome e' sempre web, indipendentemente da dove sta il compose.


Cosa succede se la rete non esiste
#

Se un compose dichiara external: true e la rete non esiste:

docker compose up
  ERROR: Network "web" declared as external, but could not be found.

Se si tenta di eliminare una rete ancora in uso:

docker compose down  # su traefik
  Network web Resource is still in use

Docker si rifiuta — comportamento di protezione corretto.

Important

L'ordine di avvio e' critico: il compose proprietario della rete deve partire per primo. Chi usa external: true deve partire dopo.

Ordine di avvio
#

Con reti external: true, l'ordine in cui avvii i compose e' obbligatorio:

# 1. Prima il proprietario della rete — la crea
docker compose up -d   # traefik — crea la rete "web"

# 2. Poi chi usa la rete
docker compose up -d   # app — usa "web" con external: true

Se avvii nell'ordine sbagliato:

ERROR: Network "web" declared as external, but could not be found.

Il problema piu' comune e' avviare i compose nell'ordine sbagliato al reboot del server. Soluzione: script di avvio ordinato, o depends_on se i servizi sono nello stesso compose.


Esempio reale — due reti con Traefik
#

graph TD
    Internet -->|443| T[Traefik]
    subgraph web["Rete web - condivisa con Traefik"]
        T -->|HTTP interno| App[app :3000]
    end
    subgraph internal["Rete internal - isolata"]
        App <-->|SQL| PG[postgres :5432]
        App <-->|cache| Redis[redis :6379]
    end
# docker-compose.yml
services:
  postgres:
    networks:
      - internal    # solo rete interna — non raggiungibile da Traefik

  app:
    networks:
      - internal    # parla con postgres e redis
      - web         # parla con Traefik

networks:
  internal:
    driver: bridge
  web:
    external: true  # esiste gia' — creata da Traefik
external: true

Con external: true si fa riferimento a una rete gia' esistente, creata da un altro compose.


Porte — esporre vs non esporre
#

# EXPOSE nel Dockerfile — solo documentazione, non apre nulla
EXPOSE 3000

# ports in docker-compose — apre la porta sull'host
ports:
  - "3000:3000"            # 0.0.0.0:3000 → tutti gli IP dell'host
  - "127.0.0.1:3000:3000"  # solo localhost → non raggiungibile da fuori
Warning

Rete Docker chiamata web e porta esposta su internet sono due cose diverse:

  • Rete web = canale virtuale tra container, NON esposta su internet
  • 0.0.0.0:443:443 = porta esposta su internet
  • 127.0.0.1:5432:5432 = solo localhost, non su internet

Traefik — exposedByDefault e label
#

Con --providers.docker.exposedbydefault=false, Traefik non espone automaticamente tutti i container sulla rete web. Un container e' visibile solo con il label esplicito:

labels:
  - "traefik.enable=true"

Se il label non c'e', Traefik ignora il container anche se e' sulla stessa rete.


Comandi essenziali
#

ComandoCosa fa
docker network-defense lsLista tutte le reti
docker network-defense inspect webDettagli: IP, container connessi, subnet, driver
docker network-defense create mynetworkCrea rete custom
docker network-defense connect mynetwork C1Aggiunge container a rete
docker network-defense disconnect web C1Rimuove container da rete
docker network-defense pruneElimina reti non usate da nessun container
docker ps -a --filter network=webTrova tutti i container su una rete specifica
Warning

Un container senza rete esplicita finisce sulla rete bridge default — dove tutti i container si vedono per IP. In produzione definisci sempre reti custom esplicite.

Tip

Per verificare che due container non si parlino (isolamento corretto): docker exec container_A ping container_B — se il ping fallisce, l'isolamento funziona.


Scenario Reale
#

Un database non deve mai essere raggiungibile da Traefik o da internet. Si mette su una rete internal senza external: true in Traefik. Solo il container applicativo, che ha bisogno di entrambe le reti, fa da tramite tra web e internal.


Note personali
#

Il problema piu' comune e' avviare i compose nell'ordine sbagliato. Se un compose usa external: true e il proprietario non e' ancora partito, il compose fallisce immediatamente con external network-defense not found.

La rete internal non deve mai avere container esposti su web — se un DB finisce su web e' un errore di configurazione, non un comportamento intenzionale.

Collegato a
#

Related