Este guia detalha o processo de empacotamento e implantação de uma aplicação frontend separada em um ambiente Docker, utilizando Nginx para servir os arquivos estáticos, configurando um balanceamento de carga e garantindo alta disponibilidade com Keepalived.
Empacotamento da Aplicação Frontend
O primeiro passo para implantar o projeto frontend é gerar os arquivos estáticos de produção. Em um projeto baseado em Node.js e ferramentas de build modernas (como Vue CLI, React Scripts ou Angular CLI), isso é tipicamente feito com um comando de build:
npm run build
Este comando criará uma pasta de saída (geralmente dist ou build) contendo os arquivos HTML, CSS, JavaScript e outros ativos compilados e otimizados para produção. Para este exemplo, assumiremos que a pasta de saída é dist.
Preparação dos Arquivos Estáticos no Host
Após a geração dos arquivos de produção, é necessário copiá-los para os diretórios no sistema host que serão montados dentro dos contêineres Docker. Para este exemplo, consideraremos três instâncias do servidor web. Você pode copiar os arquivos da seguinte forma:
# Crie e copie os arquivos para a primeira instância
sudo mkdir -p /srv/aplicacao/frontend/instancia-1
sudo cp -R dist/* /srv/aplicacao/frontend/instancia-1/
# Crie e copie os arquivos para a segunda instância
sudo mkdir -p /srv/aplicacao/frontend/instancia-2
sudo cp -R dist/* /srv/aplicacao/frontend/instancia-2/
# Crie e copie os arquivos para a terceira instância
sudo mkdir -p /srv/aplicacao/frontend/instancia-3
sudo cp -R dist/* /srv/aplicacao/frontend/instancia-3/
Garanta que esses diretórios no host contenham os arquivos estáticos completos da aplicação frontend.
Implantação dos Servidores Frontend com Nginx e Docker
Para hospedar os arquivos estáticos da aplicação frontend, serão configuradas três instâncias do Nginx, cada uma rodando em um contêiner Docker separado e expondo a aplicação em uma porta distinta. Primeiro, crie os arquivos de configuração do Nginx no seu host. Estes arquivos serão montados dentro dos contêineres.
Exemplo de Configuração Nginx para um Nó Front end (/srv/aplicacao/config/nginx-frontend-1.conf):
user nginx;
worker_processes auto; # Ajustado para usar todos os núcleos disponíveis
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on; # Habilitar compressão GZIP para melhor performance
server {
listen 6501; # Porta específica para esta instância
server_name 192.168.99.104; # Ou o IP do seu host
location / {
root /var/www/frontend-app; # Diretório onde os arquivos frontend serão montados
index index.html;
try_files $uri $uri/ /index.html; # Configuração essencial para SPAs (Single Page Applications)
}
}
}
Crie arquivos de configuração semelhantes para as instâncias 2 e 3, ajustando a porta de escuta (listen) para 6502 e 6503, respectivamente, e os caminhos de montagem para os dados do frontend.
Comandos Docker para Iniciar os Nodos Frontend:
Os contêineres serão iniciados com volumes montados para as configurações do Nginx e os arquivos estáticos da aplicação. Usaremos --net=host para simplificar a rede, mas em ambientes de produção, redes bridge Docker personalizadas são mais recomendadas.
# Iniciar a primeira instância frontend (app-web-1)
docker run -d --name app-web-1 \
-v /srv/aplicacao/config/nginx-frontend-1.conf:/etc/nginx/nginx.conf \
-v /srv/aplicacao/frontend/instancia-1:/var/www/frontend-app \
--net=host \
--privileged \
nginx
# Iniciar a segunda instância frontend (app-web-2)
docker run -d --name app-web-2 \
-v /srv/aplicacao/config/nginx-frontend-2.conf:/etc/nginx/nginx.conf \
-v /srv/aplicacao/frontend/instancia-2:/var/www/frontend-app \
--net=host \
--privileged \
nginx
# Iniciar a terceira instância frontend (app-web-3)
docker run -d --name app-web-3 \
-v /srv/aplicacao/config/nginx-frontend-3.conf:/etc/nginx/nginx.conf \
-v /srv/aplicacao/frontend/instancia-3:/var/www/frontend-app \
--net=host \
--privileged \
nginx
Certifique-se de que os arquivos nginx-frontend-2.conf e nginx-frontend-3.conf existam no host e estejam configurados com as portas e caminhos corretos, conforme mencionado anteriormente.
Configuração do Balanceamento de Carga com Nginx
Para distribuir o tráfego entre as três instâncias do servidor frontend, será configurado um balanceador de carga Nginx. Serão criadas duas instâncias de balanceamento de carga (para alta disponibilidade, que será configurada posteriormente), cada uma com sua própria configuração.
Exemplo de Configuração Nginx para o Balanceador de Carga (/srv/aplicacao/config/nginx-lb-1.conf):
user nginx;
worker_processes auto; # Ajustado para usar todos os núcleos disponíveis
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
# Configurações de proxy são importantes para balanceadores de carga
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
# Bloco upstream define os servidores backend do frontend
upstream frontend_pool {
server 192.168.99.104:6501;
server 192.168.99.104:6502;
server 192.168.99.104:6503;
}
server {
listen 6601; # Porta para o primeiro balanceador de carga
server_name 192.168.99.104; # Ou o IP do seu host
location / {
proxy_pass http://frontend_pool; # Encaminha para o pool de servidores frontend
index index.html index.htm;
}
}
}
Crie um segundo arquivo de configuração para o balanceador de carga 2 (ex: /srv/aplicacao/config/nginx-lb-2.conf), ajustando a porta de escuta para 6602.
Comandos Docker para Iniciar os Balanceadores de Carga Nginx:
# Iniciar a primeira instância do balanceador de carga (lb-node-1)
docker run -d --name lb-node-1 \
-v /srv/aplicacao/config/nginx-lb-1.conf:/etc/nginx/nginx.conf \
--net=host \
--privileged \
nginx
# Iniciar a segunda instância do balanceador de carga (lb-node-2)
docker run -d --name lb-node-2 \
-v /srv/aplicacao/config/nginx-lb-2.conf:/etc/nginx/nginx.conf \
--net=host \
--privileged \
nginx
Configuração de Alta Disponibilidade (HA) com Keepalived
Para garantir que o serviço de balanceamento de carga esteja sempre disponível, configuraremos o Keepalived em dois dos contêineres Nginx que atuam como balanceadores de carga (lb-node-1 e lb-node-2). O Keepalived usa o protocolo VRRP (Virtual Router Redundancy Protocol) para atribuir um IP virtual (VIP) a um dos servidores em um determinado momento, alternando para um servidor de backup em caso de falha do primário.
Instalação e Configuração do Keepalived nos Nodos de Balanceamento de Carga:
Primeiro, acesse cada um dos contêineres de balanceamento de carga (lb-node-1 e lb-node-2) para instalar o Keepalived e configurar seus respectivos arquivos. Uma abordagem mais robusta para produção seria montar os arquivos de configuração do Keepalived como volumes, mas para este guia, editaremos diretamente dentro dos contêineres conforme a prática original.
# Exemplo para 'lb-node-1':
docker exec -it lb-node-1 bash
apt-get update
apt-get install -y vim keepalived # '-y' para aceitar automaticamente a instalação
exit # Sair do contêiner
# Exemplo para 'lb-node-2':
docker exec -it lb-node-2 bash
apt-get update
apt-get install -y vim keepalived
exit # Sair do contêiner
Configuração do Keepalived para o Nó MASTER (/etc/keepalived/keepalived.conf dentro de lb-node-1):
Edite o arquivo /etc/keepalived/keepalived.conf dentro do contêiner lb-node-1:
vrrp_instance VI_FRONTEND_LB {
state MASTER
interface eth0 # Verifique a interface de rede do seu contêiner (pode ser ens33, eth0, etc.)
virtual_router_id 101 # ID único para este grupo VRRP
priority 100 # Prioridade mais alta para o MASTER
advert_int 1 # Intervalo de anúncio em segundos
authentication {
auth_type PASS
auth_pass senha_secreta_ha # Senha para autenticação entre os nodos Keepalived
}
virtual_ipaddress {
192.168.99.150/24 # O IP Virtual que será atribuído ao MASTER
}
}
virtual_server 192.168.99.150 6701 { # O IP virtual e a porta que os clientes acessarão
delay_loop 3
lb_algo rr # Round-robin para balanceamento entre os servidores reais
lb_kind NAT # NAT para encaminhamento de pacotes
persistence_timeout 50
protocol TCP
real_server 192.168.99.104 6601 { # Primeiro balanceador de carga Nginx
weight 100 # Peso para este servidor
}
}
Configuração do Keepalived para o Nó BACKUP (/etc/keepalived/keepalived.conf dentro de lb-node-2):
Edite o arquivo /etc/keepalived/keepalived.conf dentro do contêiner lb-node-2:
vrrp_instance VI_FRONTEND_LB {
state BACKUP # Este nó será o BACKUP
interface eth0 # Verifique a interface de rede do seu contêiner
virtual_router_id 101 # Mesmo ID do MASTER
priority 90 # Prioridade mais baixa para o BACKUP
advert_int 1
authentication {
auth_type PASS
auth_pass senha_secreta_ha # Mesma senha do MASTER
}
virtual_ipaddress {
192.168.99.150/24 # Mesmo IP Virtual do MASTER
}
}
virtual_server 192.168.99.150 6701 { # O IP virtual e a porta que os clientes acessarão
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.99.104 6602 { # Segundo balanceador de carga Nginx
weight 100
}
}
Após salvar as configurações em ambos os contêineres, inicie o serviço Keepalived em cada um (acessando o contêiner via docker exec):
# Em 'lb-node-1' e 'lb-node-2' (após entrar nos contêineres):
service keepalived start
Agora, a aplicação frontend estará acessível através do IP virtual 192.168.99.150 na porta 6701. O Keepalived garantirá a alta disponibilidade do serviço de balanceamento de carga Nginx, alternando automaticamente para o nó de backup caso o primário falhe.