Entendendo a Rede do Docker no Ubuntu Server 24.04

Quando instalamos o Docker em um Ubuntu Server 24.04, ele automaticamente cria uma infraestrutura de rede virtual que permite a comunicação entre containers e também o acesso à rede externa (internet). Neste post vamos explicar como isso funciona e mostrar esquemas visuais que ajudam a compreender a arquitetura.


1. Interfaces de Rede no Docker

No host (servidor Ubuntu), você possui uma interface física conectada à sua rede local/internet (por exemplo, enp7s0). Essa interface é responsável por enviar e receber pacotes reais.

Quando o Docker é instalado, ele cria automaticamente uma bridge virtual chamada docker0. Essa bridge atua como um switch virtual, permitindo que todos os containers conectados à rede padrão “bridge” consigam se comunicar entre si e com o host.

Cada container, ao ser iniciado, recebe uma interface de rede virtual chamada eth0. Essa interface é conectada ao host por meio de um par de interfaces virtuais (veth-pair):

  • Um lado fica dentro do container (eth0).
  • O outro lado aparece no host (por exemplo, vethXYZ) e é conectado à bridge docker0.

 

 


2. Esquema da Arquitetura de Rede Docker

A imagem abaixo mostra como as interfaces virtuais se conectam entre containers, a bridge docker0 e a interface de rede física do host:

veth-pairs: No host aparecem como veth1 e veth2, conectando respectivamente ao eth0 do Backend (172.17.0.2) e ao eth0 do MongoDB (172.17.0.3), FrontEnd(172.17.0.4).

  • Containers recebem IPs privados na sub-rede 172.17.0.0/16 (exemplo: 172.17.0.2, 172.17.0.3, 172.17.0.4).
  • docker0 funciona como o gateway dessa rede (exemplo: 172.17.0.1).
  • veth-pairs conectam cada container à bridge.


3. Fluxo de Tráfego

Saída (Container → Internet)

  1. O pacote sai do eth0 do container.
  2. Passa pelo veth-pair até a bridge docker0.
  3. É roteado/NATeado pelo host (iptables).
  4. Sai pela interface física (enp7s0) com o IP do host.

Entrada (Internet → Container)

  1. O pacote chega na interface física (enp7s0) com destino ao host.
  2. O iptables faz o redirecionamento (port forwarding) para a docker0.
  3. O pacote segue para o veth-pair do container correto.
  4. Chega ao eth0 dentro do container.

4. Benefícios do Modelo

  • Isolamento: cada container tem sua própria pilha de rede.
  • Flexibilidade: é possível criar redes adicionais (bridge, overlay, macvlan, etc.).
  • Conectividade: containers podem se comunicar entre si e acessar serviços externos sem necessidade de configuração manual complicada.

5. Como Funciona

O que acontece quando você faz docker run -p 3000:3000 backend é mais ou menos isso:

  1. O container backend abre a porta 3000 interna (172.17.0.2:3000).

  2. O Docker cria regras no iptables do host:

# Redireciona conexões que chegam na porta 3000 do host para o container
iptables -t nat -A DOCKER -p tcp --dport 3000 -j DNAT --to-destination 172.17.0.2:3000
# Permite que a resposta volte para o cliente
iptables -t nat -A POSTROUTING -s 172.17.0.2 -j MASQUERADE
  1. Assim, quando alguém acessa http://IP_DO_HOST:3000, o pacote entra na interface física (eth0), passa pelo NAT do iptables, é redirecionado para o container backend, e volta pelo mesmo caminho.


📊 Mini-diagrama extra (focado no NAT/iptables da porta 3000):

Cliente (Rede Pública)
|
v
[ eth0 (Host) ] --- iptables DNAT ---> [ docker0 ]
|
veth1 <-> Backend (172.17.0.2:3000)

E as regras NAT/masquerade garantem que o Backend responda como se fosse o próprio host.

6. Exemplo prático

configuração considerando os requisitos:

  • Containers:

    • Backend (porta 3000)

    • Frontend (porta 80)

    • MongoDB (porta interna, sem exposição externa)

  • Regras:

    • O MongoDB deve ser acessível apenas pela rede interna Docker, não sendo exposto ao host nem ao público.

    • O Frontend deve estar acessível externamente via porta 80.

    • O Backend deve estar acessível externamente via porta 3000.

    • Tanto Frontend quanto Backend devem conseguir acessar o MongoDB via rede interna.


🔹 Passo 1: Criar uma rede Docker bridge personalizada

docker network create app_net

Essa rede bridge (app_net) será usada para a comunicação interna entre os containers.


🔹 Passo 2: Subir os containers

MongoDB (somente rede interna, sem exposição externa)

docker run -d \
--name mongodb \
--network app_net \
mongo:latest

Aqui não usamos -p, ou seja, o MongoDB não é acessível externamente, apenas pela rede interna app_net.


Backend (exposto na porta 3000)

docker run -d \
--name backend \
--network app_net \
-p 3000:3000 \
-e MONGO_URL="mongodb://mongodb:27017/meubanco" \
meu-backend:latest

O -p 3000:3000 expõe o backend para acesso externo.
Dentro da rede interna, ele acessa o MongoDB pelo hostname mongodb.


Frontend (exposto na porta 80)

docker run -d \
--name frontend \
--network app_net \
-p 80:80 \
-e API_URL="http://backend:3000" \
meu-frontend:latest

O -p 80:80 expõe o frontend externamente.
Ele se comunica com o backend pelo hostname interno backend.


🔹 Passo 3: Verificar conectividade

docker exec -it backend ping mongodb
docker exec -it frontend ping backend

Ambos devem resolver os nomes automaticamente, já que estão na rede app_net.


Resumo do fluxo:

  • Usuário acessa http://servidor:80 → Frontend.

  • Frontend se comunica com Backend pela rede interna (http://backend:3000).

  • Backend acessa MongoDB internamente (mongodb:27017).

  • MongoDB não é exposto ao host, garantindo segurança.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *