Escalando horizontalmente sua aplicação com NGINX + DOCKER
- #Docker
- #Node.js
Sabe quando a sua aplicação começa a bater no teto de CPU e memória? 🤯 A primeira reação costuma ser dar um upgrade na máquina (a famosa escala vertical). Mas a verdadeira resiliência mora na escala horizontal: colocar múltiplos servidores trabalhando em paralelo. E para que esse tráfego seja distribuído de forma inteligente e transparente, o Load Balancer (Balanceador de Carga) entra em cena. 🚦
Montei um laboratório prático usando Docker 🐳 e Nginx 🌐 atuando como Proxy Reverso e Load Balancer. Vamos dissecar essa infraestrutura!
🏗️ A Arquitetura do Lab
A topologia é clássica e super eficiente. Todo o tráfego externo bate em um único ponto de entrada, que faz o roteamento interno para as instâncias:

🐳 O Motor: Docker Compose
Para orquestrar tudo isso sem dor de cabeça, usamos o docker-compose.yml. Em vez de configurar redes na mão, aproveitamos a inteligência nativa do Docker.
Temos um serviço web (nosso Nginx) expondo a porta 8080, e três serviços independentes em Node.js (application1, application2, application3).
✨ O pulo do gato técnico: O Docker cria uma rede interna e um servidor DNS automaticamente. O Nginx não precisa saber o IP dinâmico de cada aplicação; ele acha as instâncias pelo próprio nome do serviço! Além disso, usamos bind mounts nos volumes para que o código reflita em tempo real, excelente para o ambiente de dev 🔥.
🧠 O Cérebro: nginx.conf
A mágica do roteamento acontece no arquivo de configuração, que injetamos no Nginx via volume. Ele se divide em duas partes de ouro:
1. O Pool de Servidores (upstream)
upstream backend_apps {
server app1:3000;
server app2:3000;
server app3:3000;
}
Aqui declaramos o nosso cluster chamado backend_apps. O Nginx usa aquele DNS do Docker para achar exatamente onde cada contêiner está rodando. 🎯
2. O Repasse de Headers (server)
server {
listen 80;
location / {
proxy_pass http://backend_apps;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
⚠️ Atenção aqui: Se você omitir as linhas do proxy_set_header, suas instâncias Node.js vão achar que todas as requisições estão vindo do IP interno do Nginx. Repassar o $host e o $remote_addr garante que o backend receba o IP real de quem originou o clique. Isso é vital para logs, auditoria e Rate Limiting! 🛡️
🔀 Estratégias de Balanceamento
Como o Nginx divide esse bolo de requisições? Basta adicionar uma diretiva simples no bloco upstream:
- 🔄 Round Robin (O Padrão): Distribui sequencialmente (App 1, App 2, App 3...). É previsível e excelente para aplicações stateless rodando em hardwares idênticos.
- ⚖️ Least Connected (
least_conn;): O Nginx manda o tráfego para a instância que tem menos conexões ativas no momento. Perfeito para APIs com rotas pesadas misturadas com rotas rápidas. - 📌 IP Hash (
ip_hash;): Faz um cálculo baseado no IP do cliente para garantir que ele caia sempre no mesmo servidor (Sticky Sessions). Útil se sua aplicação guarda estado na memória local. - 🏋️ Weighted (Pesos): Permite direcionar mais tráfego para servidores específicos. Ex:
server app1:3000 weight=3;faz o app1 receber o triplo de requisições. Ótimo se uma das máquinas for mais potente. - ⚡ Least Time (
least_time header;): Roteia para o nó com a menor latência de resposta. (Nota: Essa maravilha é exclusiva da versão comercial NGINX Plus. Na versão open-source, vá deleast_connque é sucesso!).
🏁 Conclusão
Implementar um Load Balancer não é só sobre aguentar mais acessos, é sobre alta disponibilidade 💪. Se o contêiner app2 morrer por falta de RAM, o Nginx detecta a falha e para de mandar tráfego para ele na mesma hora, mantendo seu sistema no ar. Dominar esses conceitos é o que separa sistemas frágeis de arquiteturas prontas para produção! 🚀



