Por que containers Docker perdem conexão na bridge network e como resolver intermitência em produção

Por · Publicado em · 8 min de leitura

Cabos de rede azuis conectados em um painel/patch panel, foco nos conectores e fundo desfocado
Conexões físicas em painel de rede, representando infraestrutura e diagnóstico de conectividade. Foto: Brett Sayles / Pexels

Se os containers Docker perdem conexão na bridge network de forma intermitente, o diagnóstico certo evita horas de tentativa e erro. A causa costuma estar em MTU/PMTU, conntrack/NAT, rp_filter/ARP ou DNS interno. Abaixo mostro como identificar cada raiz e aplicar correções seguras em produção.

Sintomas e quando a intermitência aparece

Intermitência na bridge se manifesta como timeouts, resets (RST) e conexões que funcionam e, de repente, quebram. Às vezes só cargas grandes falham; pings curtos passam.

O padrão comum: serviços sob Docker ficam acessíveis via porta publicada, mas clientes internos ou externos observam falhas ocasionais, principalmente sob pico, quando muitos containers iniciam/param ou após mudanças de rede no host.

  • TCP conecta, recebe alguns KB e trava até timeout.
  • Uploads/downloads grandes falham; requisições pequenas funcionam.
  • Mensagens no kernel sobre conntrack/ARP ou pacotes ‘martian’.
  • DNS resolve lento ou intermitente dentro dos containers.

Causas técnicas mais comuns na Docker bridge

Algumas raízes aparecem repetidamente em incidentes reais de produção. Entenda o mecanismo para aplicar a correção certa.

A boa notícia: a maioria tem diagnóstico objetivo com poucas verificações no host e nos containers.

  • MTU/PMTU: MTU do veth/docker0 não combina com a rede física/túneis, gerando blackhole para pacotes grandes.
  • Conntrack/NAT: tabela nf_conntrack lota, portas efêmeras esgotam e sessões caem ao acaso.
  • rp_filter/rotas: roteamento assimétrico, VRRP/VPN ou múltiplas NICs fazem o kernel descartar respostas legítimas.
  • ARP/neighbour cache: entradas obsoletas ou GC agressivo após churn de containers.
  • DNS 127.0.0.11: o DNS embutido do Docker sofre sob alto QPS ou timeouts ruins.
  • Regras DOCKER-USER/iptables: políticas ‘drop’ atingem tráfego de docker0 sem exceções adequadas.

Diagnóstico rápido no host e nos containers

Faça um triagem objetiva antes de alterar configuração. Busque sinais de MTU, conntrack e quedas por firewall/roteamento.

Execute do host e de um container afetado. Guarde os horários e compare com picos de tráfego.

# 1) Sinais no kernel (conntrack, ARP/neighbor, martian)
dmesg -T | egrep -i 'conntrack|nf_conntrack|neighbor|arp|martian|FRAG'

# 2) Estado de conntrack e portas efêmeras
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
ss -s
cat /proc/sys/net/ipv4/ip_local_port_range

# 3) PMTU/MTU: teste DF e caminho
GW=$(ip route | awk '/default/ {print $3; exit}')
ping -c 3 -M do -s 1472 "$GW" || echo "Possível MTU < 1500 no caminho"
tracepath -n "$GW" | tail -n +1

# 4) ARP/neigh suspeito (incomplete/failed)
ip -s neigh | egrep -i 'FAILED|INCOMPLETE' -n || true

# 5) Regras do Docker e DOCKER-USER
iptables -S DOCKER-USER 2>/dev/null || true
iptables -t nat -S | sed -n '1,120p' 2>/dev/null || true

# 6) De dentro de um container afetado: DNS e MTU
getent hosts example.com || nslookup example.com || dig +short example.com || true
ip route show
echo $(cat /sys/class/net/eth0/mtu) MTU-no-container

MTU e PMTU: detectar e corrigir sem derrubar tudo

Falhas só com payloads grandes quase sempre indicam MTU/PMTU. Em clouds com túneis (VXLAN/GRE), a MTU efetiva costuma ser 1450/1460. Se docker0/eth0 do container ficam em 1500, surge blackhole.

Confirme com ping DF. Se menor MTU for necessária, ajuste a MTU do Docker para alinhar com a rede. Requer restart do Docker e recriação da bridge, planeje janela.

  • Valide com ping -M do para o gateway/serviço.
  • Ajuste MTU no daemon do Docker para propagar aos veths.
  • Teste novamente e monitore erros de fragmentação.
# Teste PMTU (ajuste o destino para um serviço fora do host)
ping -c 3 -M do -s 1472 $DEST || echo "Tente 1432/1400 para descobrir a MTU segura"

# Ajuste de MTU no Docker (crie/edite /etc/docker/daemon.json)
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
  "mtu": 1450
}
EOF

# Reinicie com cuidado (interrompe containers)
sudo systemctl restart docker

# Verifique
aioctl=$(ip -o link show docker0 | awk '{print $2,$9,$10,$11}')
echo "docker0 ->" $ioctl
ip -o link show | grep veth | head -n 3

Conntrack, NAT e portas efêmeras: limites e tuning

Tabela nf_conntrack cheia derruba conexões novas e pode matar as existentes. Tráfego com muito NAT também sofre se o range de portas efêmeras é curto.

Ajuste limites de conntrack com parcimônia, amplie a faixa de portas e, se você gerencia o firewall manualmente, prefira MASQUERADE com random-fully para reduzir colisões de 5‑tuple.

  • Monitore count vs max; mantenha folga saudável.
  • Amplie ip_local_port_range em hosts de saída intensa.
  • Evite regras que forcem inspeção cara em todo pacote.
# Medir e ajustar conntrack
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# Exemplo: elevar (persistir em /etc/sysctl.d)
echo 'net.netfilter.nf_conntrack_max = 524288' | sudo tee /etc/sysctl.d/90-conntrack.conf
sudo sysctl --system

# Portas efêmeras mais amplas
sudo sysctl -w net.ipv4.ip_local_port_range="10240 65535"
echo 'net.ipv4.ip_local_port_range = 10240 65535' | sudo tee /etc/sysctl.d/90-ports.conf
sudo sysctl --system

# Se você administra NAT manualmente (fora das regras do Docker):
# iptables -t nat -C POSTROUTING -o eth0 -j MASQUERADE --random-fully || \
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE --random-fully

ARP, vizinhança e rp_filter: rotas que somem

Roteamento assimétrico (VPN, VRRP, múltiplas NICs) com rp_filter estrito faz o kernel descartar respostas legítimas. ARP/neighbour cache pequeno, sob churn, induz falhas intermitentes.

Aplique rp_filter ‘loose’ onde há assimetria e aumente os limiares do neighbour GC. Mude com cautela e registre as alterações.

  • Procure ‘martian source’ nos logs.
  • Confirme a rota de retorno com ip route get.
  • Aumente gc_thresh em hosts com muitas peers/containers.
# rp_filter atual
sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.default.rp_filter
# Tornar ‘loose’ (2) se há assimetria/VRRP/VPN
sudo sysctl -w net.ipv4.conf.all.rp_filter=2
sudo sysctl -w net.ipv4.conf.default.rp_filter=2

echo -e 'net.ipv4.conf.all.rp_filter=2\nnet.ipv4.conf.default.rp_filter=2' | \
  sudo tee /etc/sysctl.d/90-rpfilter.conf

# Neighbour cache mais folgado
sysctl net.ipv4.neigh.default.gc_thresh1 net.ipv4.neigh.default.gc_thresh2 net.ipv4.neigh.default.gc_thresh3
sudo bash -c 'cat > /etc/sysctl.d/90-neigh.conf <<EOF
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
EOF'
sudo sysctl --system

# Limpar entradas problemáticas (impacta momentaneamente a resolução ARP)
sudo ip neigh flush dev docker0 || true

DNS 127.0.0.11 e firewall: quando não é a rede

A resolução embutida (127.0.0.11) pode virar gargalo sob alto QPS ou parâmetros ruins de timeout. Em ambientes restritos, DOCKER-USER com DROP padrão derruba tráfego da bridge.

Teste com DNS externo/cacher e ajuste dns_opt no Compose. Revise DOCKER-USER garantindo exceções claras antes de um DROP amplo.

  • Use um resolvedor local (ex.: 10.0.0.53) para cache.
  • Reduza timeout/attempts para falhar rápido e tentar outro DNS.
  • Permita RELATED,ESTABLISHED e tráfego de docker0 no firewall.
# docker-compose.yml (trecho)
services:
  app:
    image: example/app
    dns:
      - 10.0.0.53
      - 1.1.1.1
    dns_opt:
      - timeout:1
      - attempts:3
    # ... restante do serviço

Observabilidade, testes e próximos passos

Depois de aplicar correções, valide sob carga e monitore. Métricas de conntrack, quedas TCP e latência de DNS ajudam a prevenir regressões.

Implemente health checks para retirar instâncias do tráfego ao primeiro sinal de falha, e um proxy reverso bem configurado para failover/renovação de certificados.

  • Colete métricas com Prometheus/Grafana e alertas úteis.
  • Centralize logs (kernel, iptables, apps) para correlação.
  • Automatize readiness checks e circuit breakers no app.
  • Teste PMTU em pipelines de deploy e após mudanças de rede.
  • Evite a bridge ‘default’; prefira redes user-defined isoladas.

Perguntas frequentes

Como saber se o problema é MTU/PMTU ou outra coisa?

Se pings pequenos funcionam e pacotes grandes com DF falham, é forte indício de MTU/PMTU. Tracepath ajuda a revelar o salto que reduz MTU. Já quedas aleatórias sob pico com mensagens de nf_conntrack apontam para conntrack/NAT. Logs de ‘martian’ sugerem rp_filter/rotas.

Aumentar nf_conntrack_max resolve definitivamente?

Ajuda a aliviar picos, mas não é bala de prata. Se o padrão de tráfego cria muitas conexões curtas, ajuste também timeouts, amplie portas efêmeras e revise o desenho (pooling/reuso de conexões). Monitore o count para evitar crescer sem necessidade.

Desativar rp_filter é seguro?

Evite desativar totalmente. Use modo ‘loose’ (2) quando há roteamento assimétrico, VRRP ou VPN. O modo estrito em hosts multi-homed causa falsos positivos e descartes. Documente a mudança e monitore logs de ‘martian’ após o ajuste.

Devo usar DNS embutido do Docker ou um resolvedor externo?

Para cargas leves, o DNS embutido funciona bem. Em alto QPS ou latências sensíveis, use um resolvedor local em cache (ex.: unbound/dnsmasq) e aponte os serviços via dns no Compose. Ajuste dns_opt para timeouts curtos e múltiplos servidores.

User-defined bridge melhora a estabilidade?

Sim. Redes user-defined isolam domínios de broadcast, têm regras mais previsíveis e DNS por serviço. Elas reduzem colisões e facilitam políticas de firewall. Evite concentrar todos os serviços na bridge ‘default’; crie redes por domínio lógico.

Quer estabilizar a rede dos seus containers?

Se você enfrenta intermitência na Docker bridge e precisa de um plano de diagnóstico e correção com baixo risco, vamos conversar sobre o seu cenário e próximos passos práticos.

Falar sobre diagnóstico Docker

Veja também