Poupe 15% em todos os serviços de alojamento

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código: Skills Começar a trabalhar
Secções
Administração Segurança

Como Instalar HAProxy com Docker Compose em Ubuntu VPS

Um serviço web num VPS é fácil de expor diretamente — até que queira uma porta pública limpa, a liberdade de trocar o backend mais tarde, ou uma forma mais segura de parar de enviar tráfego para algo avariado. É nesse ponto que um proxy deixa de parecer “algo para grandes equipas de infraestrutura” e começa a parecer prático.

intro

HAProxy encaixa bem nesse papel. Pense nele como o gestor de tráfego sentado em frente da sua aplicação: os pedidos chegam primeiro ao HAProxy, e o HAProxy decide para onde devem ir a seguir. Não precisa de um grande cluster para beneficiar disso. Mesmo num único VPS Ubuntu 24.04, oferece-lhe uma separação mais limpa entre a internet e o serviço que está realmente a executar.

Este guia mantém a primeira implementação intencionalmente estruturada: um VPS Ubuntu 24.04, Docker Compose, um contentor HAProxy, um backend de demonstração, e prova de que o encaminhamento realmente funciona.

Por que o HAProxy é Importante Antes de Você Precisar Dele

Imagine uma pequena VPS executando um aplicativo perfeitamente hoje. Ele responde em uma porta, o site carrega e tudo parece bom. O atrito começa quando você quer um ponto de entrada público estável, a opção de substituir o backend posteriormente sem alterar o endereço público, ou uma camada frontal que possa parar de enviar tráfego para um serviço com falha. Expor o aplicativo diretamente começa a parecer frágil surpreendentemente rápido.

whymatters

Esses requisitos apontam para a mesma camada ausente: um ponto de entrada controlado entre a internet e seu aplicativo. O HAProxy fornece essa camada. Os clientes se conectam ao HAProxy primeiro, e o HAProxy decide para onde cada solicitação vai em seguida.

Essa separação é útil mesmo antes de você ter vários servidores. Ela oferece uma borda pública mais limpa agora e um caminho mais seguro para mudanças posteriores, como substituição de backend, roteamento com reconhecimento de saúde e HTTPS. O resto do guia mostra esse padrão em sua forma de funcionamento mais simples e o verifica com um caminho de solicitação real.

Termos Rápidos do HAProxy Que Facilitam o Resto deste Guia

quick

Você só precisa de um pequeno conjunto de vocabulário para seguir uma primeira implantação do HAProxy com confiança. A tabela abaixo cobre os termos que importam neste guia.

TermoSignificado em linguagem simples
🌐 reverse proxyUm serviço voltado para o público que recebe solicitações primeiro e as passa para outro serviço interno.
⚖️ load balancerUma camada frontal que pode distribuir solicitações entre mais de um alvo de backend.
🚪 frontendO lugar onde os clientes se conectam ao HAProxy.
🧩 backendO serviço ou servidor para o qual o HAProxy envia a solicitação a seguir.
❤️ health checkUma forma de o HAProxy perceber se um backend deve continuar recebendo tráfego.
🐳 imageUm modelo de aplicação empacotado usado para criar contêineres.
📦 containerUma instância em execução de uma imagem.

Para este guia, reverse proxy é o primeiro modelo mental a manter em mente. O HAProxy fica na frente de algo e controla a transferência. Load balancing é a capacidade estendida que se torna útil quando você adiciona vários servidores de backend posteriormente.

Os dois termos que mais importam quando você abre a configuração são frontend e backend. O frontend é onde o cliente chega. O backend é para onde o HAProxy envia a solicitação a seguir. Um health check importa porque permite que o HAProxy perceba quando um alvo deve parar de receber tráfego.

O Que HAProxy Faz Bem — e O Que Este Guia Intencionalmente Ignora

whatgood

Se você imaginar sua stack como um prédio de escritórios, HAProxy é a recepção: o tráfego chega lá primeiro, é direcionado para a sala certa, e para de ser enviado para uma sala que está claramente indisponível.

Neste guia, isso se traduz em três trabalhos relevantes para iniciantes:

  1. aceitar requisições HTTP recebidas
  2. encaminhá-las para o backend de demonstração
  3. monitorar se esse backend está saudável o suficiente para continuar recebendo tráfego

Isso já é útil com um backend porque oferece uma borda pública controlada na frente da aplicação.

Mais tarde, o mesmo padrão escala de forma limpa. Você pode substituir o backend, adicionar mais backends, introduzir HTTPS, ou deixar HAProxy distribuir tráfego entre múltiplos destinos em vez de apenas um. Para manter o primeiro passo ensinável, este guia permanece em modo HTTP e intencionalmente ignora terminação TLS, ACLs, rate limiting, stick tables e pares HA. Todos esses são tópicos reais de HAProxy. Eles apenas não são o ponto de partida certo para uma primeira implantação funcional.

O Que Você Está Construindo e O Que Precisa Primeiro

buildingsetup

Antes de criar arquivos, é útil ver a forma final da stack. A implantação neste guia se parece com isto:

Client browser or curl
        |
        v
HAProxy frontend (:80)
        |
        v
demo backend service (demo:5678)

Optional local-only validation:
HAProxy stats frontend (127.0.0.1:8404/stats)

Docker Compose é o caminho principal aqui porque mantém a primeira instalação reproduzível, visível e fácil de editar. Em vez de construir uma imagem personalizada no primeiro dia, você mantém a configuração HAProxy no host, monta-a no container e inicia toda a stack a partir de um arquivo. Em um VPS Ubuntu auto-gerenciado — por exemplo, um VPS AlexHost — isso é um ajuste limpo porque o layout permanece fácil de inspecionar.

💡 Dica: Este guia usa Docker Compose mais um haproxy.cfg montado por bind propositalmente. É o caminho de primeira instalação mais transparente porque você pode editar a configuração do proxy diretamente sem adicionar uma etapa de construção de imagem.

Antes de começar, certifique-se de que tem estes itens básicos em vigor:

  • Ubuntu 24.04 VPS
  • Docker Engine instalado
  • Docker Compose v2 disponível através de docker compose
  • Acesso ao terminal e permissão para executar Docker
  • Porta 80 disponível no host
  • HTTP de entrada permitido se você usar UFW ou regras de firewall do lado do provedor

Primeiro, verifique sua versão do Ubuntu

lsb_release -a

ubuntu-version

Em seguida, confirme que Docker e Compose moderno estão disponíveis:

docker --version
docker compose version

docker-version

Se ambos os comandos retornarem informações de versão, o lado do runtime do container está pronto e você pode se manter focado em HAProxy em vez de fazer um desvio para a instalação do Docker.

Em seguida, certifique-se de que a porta 80 não está já em uso, depois verifique se UFW está ativo e se HTTP já está permitido:

sudo ss -tlnp | grep -E ':(80)s' || true
sudo ufw status
sudo ufw allow 80/tcp

ufw-status

✏️ NOTA: Nenhuma saída da verificação ss geralmente significa que a porta 80 está livre. Se você vir nginx, apache2, caddy ou outro serviço já escutando lá, corrija isso primeiro. É uma etapa de verificação prévia de dez segundos que economiza muita confusão depois.

No exemplo acima, sudo ufw status mostra Status: active, e 80/tcp já está presente na lista de permissões. É por isso que sudo ufw allow 80/tcp retorna Skipping adding existing rule em vez de adicionar uma nova. Essa saída é normal e simplesmente significa que a regra de firewall já estava em vigor.

Criar a Pasta do Projeto e o Arquivo Compose

Comece criando uma pequena pasta de projeto para os dois arquivos que esta primeira implementação precisa:

mkdir -p ~/haproxy-docker
cd ~/haproxy-docker

mkdir

Depois disso, o layout deve ser o menor possível:

~/haproxy-docker/
├── compose.yaml
└── haproxy.cfg

Agora crie compose.yaml e use este conteúdo exato:

services:
  demo:
    image: hashicorp/http-echo:1.0
    command: ["-listen=:5678", "-text=Hello from the HAProxy demo backend"]
    restart: unless-stopped

  haproxy:
    image: haproxy:3.4.1
    depends_on:
      - demo
    ports:
      - "80:80"
      - "127.0.0.1:8404:8404"
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    sysctls:
      net.ipv4.ip_unprivileged_port_start: "0"
    restart: unless-stopped

Este arquivo conecta os containers, mas ainda não define a lógica de requisição do HAProxy. Ele diz ao Docker quais imagens executar, quais portas publicar e de onde o arquivo de configuração do HAProxy será montado no host.

As seguintes configurações são as que mais importam para uma primeira implementação limpa:

Configuração do ComposePor que está aqui
hashicorp/http-echo:1.0Oferece um backend de demonstração minúsculo e previsível sem ensinar um segundo servidor web ao mesmo tempo.
haproxy:3.4.1Usa uma tag estável fixada em vez de latest, o que mantém o guia menos frágil ao longo do tempo.
depends_onInicia o serviço demo antes do HAProxy, o que é útil para a ordem de primeira execução.
80:80Publica o listener HTTP principal na porta web padrão que os leitores esperam.
127.0.0.1:8404:8404Mantém a página de estatísticas disponível para validação local sem expô-la publicamente por padrão.
./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:roMonta seu arquivo de configuração visível no lado do host na imagem oficial do HAProxy como somente leitura.
sysctls com net.ipv4.ip_unprivileged_port_start: “0”Permite que o container HAProxy não-root se vincule a portas baixas como 80.
restart: unless-stoppedOferece um padrão VPS prático: reiniciar após falha ou reinicialização, mas respeitar uma parada manual intencional.

Um detalhe a mais importa aqui: não há rede Docker personalizada neste arquivo porque o Docker Compose cria uma rede padrão automaticamente. Isso oferece DNS de nome de serviço dentro do projeto, é por isso que o HAProxy será capaz de alcançar o backend como demo:5678 sem fiação extra.

⚠️ Aviso: A porta 80 é uma porta privilegiada, portanto a linha sysctls não é decorativa. Alterar o mapeamento de host para 8080:80 não remove o requisito de porta privilegiada dentro do container se o HAProxy ainda se vincular a :80 internamente.

Escrever e Validar um haproxy.cfg Mínimo

Com a fiação do container em vigor, HAProxy ainda precisa de instruções sobre onde o tráfego chega, para onde deve ir e como a saúde do backend é verificada. Crie haproxy.cfg a seguir:

global
    log stdout format raw local0

defaults
    mode http
    timeout connect 5s
    timeout client 30s
    timeout server 30s

frontend http
    bind :80
    default_backend demo_backend

backend demo_backend
    balance roundrobin
    server demo1 demo:5678 check

frontend stats
    bind :8404
    stats enable
    stats refresh 10s
    stats uri /stats

Esta é uma configuração mínima, mas não é uma configuração descartável. log stdout format raw local0 é a escolha de logging amigável ao container porque Docker pode expor stdout facilmente, e mode http em defaults mantém todo o exemplo em modo HTTP para que o comportamento do listener e do backend permaneçam consistentes e legíveis.

✏️ NOTA: Um detalhe vale a pena ser destacado antes da análise da seção: balance roundrobin é definido explicitamente porque versões mais recentes do HAProxy alteraram o algoritmo padrão do backend para random, e roundrobin é mais fácil de ensinar de forma previsível numa primeira passagem.

Aqui está a análise em linguagem simples de cada seção:

SeçãoLinhas-chaveO que faz
globallog stdout format raw local0Envia logs para stdout para que o logging do Docker permaneça direto.
defaultsmode http, timeoutsEstabelece comportamento HTTP de base e valores de timeout sensatos.
frontend httpbind :80, default_backend demo_backendCria o listener público e o conecta à definição do backend.
backend demo_backendbalance roundrobin, server demo1 demo:5678 checkDiz ao HAProxy qual serviço usar e para monitorar sua saúde.
frontend statsbind :8404, stats enable, stats uri /statsAdiciona uma página de validação local opcional para que você possa ver o status em tempo de execução mais tarde.

Você pode notar uma coisa ausente: option forwardfor. Essa omissão é intencional no caminho base. Preservar o IP do cliente original é útil mais tarde, mas este primeiro deployment é sobre provar roteamento e saúde do backend, não ensinar comportamento de cabeçalho com um container de demonstração que não torna esse sinal especialmente valioso.

💡 Dica: Sempre valide a configuração do HAProxy antes de iniciar a stack completa. Como esta configuração se refere ao backend pelo seu nome de serviço Compose (demo), inicie esse backend primeiro para que HAProxy possa resolvê-lo durante a validação.

Execute a validação do mesmo diretório do projeto:

docker compose up -d demo
docker compose run --rm --no-deps haproxy haproxy -V -c -f /usr/local/etc/haproxy/haproxy.cfg

success

Se o segundo comando terminar com Configuration file is valid, você já provou que HAProxy pode analisar o arquivo corretamente e resolver o alvo do backend antes de qualquer listener ao vivo iniciar.

Inicie a Stack e Prove que o Proxy Funciona

Assim que a config for validada, inicie a stack em modo detached:

Como o passo de validação já iniciou demo, este comando principalmente traz HAProxy e reconcilia a stack completa de dois serviços:

docker compose up -d

start-cmpose

Depois verifique se ambos os containers estão vivos:

docker compose ps

compose-status

Essa visualização de processos é apenas o primeiro checkpoint. Confirma que Docker iniciou os containers, mas ainda não que HAProxy está roteando tráfego com sucesso para o backend. O próximo request verifica o caminho de dados real.

Agora execute o teste de roteamento real a partir da VPS:

curl -i http://127.0.0.1

valid

O sinal de sucesso é HTTP/1.1 200 OK mais o corpo da resposta contendo Hello from the HAProxy demo backend. Algumas compilações de http-echo envolvem esse texto em uma pequena resposta HTML, então foque na frase do corpo mais do que na formatação exata.

Se quiser uma prova em nível de navegador, abra http://YOUR_SERVER_IP a partir de outra máquina.

browser-valid

Para uma segunda superfície de validação, verifique a página de stats somente local a partir da VPS:

curl http://127.0.0.1:8404/stats

Na página de stats, os sinais mais úteis são um frontend nomeado http, um backend nomeado demo_backend, uma linha de servidor nomeada demo1, status mostrado como UP, e geralmente um valor de last-check como L4OK in 0ms. Também mantenha em mente uma pequena nuance do Docker: depends_on com sintaxe curta controla a ordem de inicialização, mas não aguarda um serviço ficar saudável. Se o primeiro curl falhar uma vez logo após a inicialização, aguarde alguns segundos e tente novamente antes de assumir que a config está errada.

A diferença entre estado de processo e sucesso real é mais fácil de manter clara em forma de tabela:

EstadoO que isso lhe diz
Containers estão runningDocker iniciou os processos.
curl -i http://127.0.0.1 retorna 200 OK e a frase demoHAProxy está realmente roteando tráfego para o backend.
Página de stats mostra demo1 como UPHAProxy vê o backend como saudável.

Erros Comuns na Primeira Execução e Correções Rápidas

mistakes

Se a configuração não funcionar imediatamente, resista ao impulso de reescrever ambos os ficheiros de uma vez. A maioria das falhas na primeira execução nesta stack são previsíveis, e ficam muito mais fáceis de corrigir quando você muda uma variável de cada vez.

Use esta matriz como camada de diagnóstico rápido:

  • HAProxy sai imediatamente

    Causa provável: haproxy.cfg está em falta.

    Correção rápida: Certifique-se de que haproxy.cfg existe junto a compose.yaml.

    Por que acontece: A imagem oficial não vem com uma configuração pronta para usar.


  • Erro diz que não consegue abrir /usr/local/etc/haproxy/haproxy.cfg

    Causa provável: Caminho de bind-mount incorreto.

    Correção rápida: Verifique ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro exatamente.

    Por que acontece: HAProxy não consegue iniciar sem um ficheiro de configuração válido.


  • Erro diz Permission denied na porta 80

    Causa provável: Problema de ligação a porta privilegiada.

    Correção rápida: Mantenha net.ipv4.ip_unprivileged_port_start: “0” no Compose, ou mude tanto HAProxy como a porta publicada para 8080.

    Por que acontece: O contentor é executado como utilizador não-root haproxy.


  • Você mudou o mapeamento para 8080:80 e ainda recebe um erro de ligação

    Causa provável: HAProxy ainda se liga a :80 dentro do contentor.

    Correção rápida: Mude tanto o mapeamento do anfitrião como a linha bind interna se se afastar da porta 80.

    Por que acontece: A regra de porta privilegiada aplica-se também dentro do contentor.


  • Porta 80 já está em uso

    Causa provável: Outro serviço é proprietário da porta do anfitrião.

    Correção rápida: Execute novamente a verificação ss e pare ou mude o serviço em conflito.

    Por que acontece: Apenas um processo pode escutar na mesma porta do anfitrião.


  • Verificação de sintaxe relata unknown keyword ou erros específicos de linha

    Causa provável: Erro de digitação na configuração HAProxy.

    Correção rápida: Execute novamente a verificação de sintaxe e corrija a linha exata que relata.

    Por que acontece: O analisador de HAProxy é rigoroso, o que é útil quando o usa intencionalmente.


  • Contentores estão ativos, mas curl não retorna a resposta de demonstração

    Causa provável: Caminho de encaminhamento está errado.

    Correção rápida: Verifique novamente default_backend demo_backend, server demo1 demo:5678 check, e o nome do serviço demo.

    Por que acontece: Um contentor em execução não é prova de um caminho frontend-para-backend correto.


  • curl local funciona mas o site é inacessível de fora

    Causa provável: Firewall ou regra de segurança do fornecedor.

    Correção rápida: Abra a porta 80 em UFW e em qualquer firewall do lado do fornecedor.

    Por que acontece: A publicação local pode funcionar mesmo quando o acesso público ainda está bloqueado.

⚠️ Aviso: Mude uma coisa de cada vez. Se editar compose.yaml e haproxy.cfg cegamente, fica muito mais difícil determinar se a falha é um problema de caminho de ficheiro, um problema de porta, ou um problema de encaminhamento.

Quando precisa de evidência rápida, mantenha estes comandos à mão:

docker compose logs haproxy
docker compose ps
docker compose up -d demo
docker compose run --rm --no-deps haproxy haproxy -V -c -f /usr/local/etc/haproxy/haproxy.cfg
sudo ss -tlnp | grep -E ':(80|8404)s' || true

Estes são os três padrões de alerta mais dignos de reconhecer à primeira vista:

[ALERT] ... Cannot open configuration file /usr/local/etc/haproxy/haproxy.cfg : No such file or directory
[ALERT] ... Starting frontend http: cannot bind socket (Permission denied) [0.0.0.0:80]
[ALERT] ... parsing [/usr/local/etc/haproxy/haproxy.cfg:12] : unknown keyword 'chekc'; did you mean 'check' maybe?

Essa é a parte tranquilizadora de uma pequena implementação inicial: as formas de falha são geralmente pequenas também. Você não precisa começar do zero. Você precisa identificar qual camada está reclamando e corrigir essa uma coisa primeiro.

Para Onde Ir Após a Instalação

Assim que a demo com um backend funcionar, a arquitetura já é útil. O próximo passo real é substituir o container de demo pela sua aplicação real, mantendo a mesma estrutura HAProxy. Depois disso, adicione HTTPS/TLS como um passo de acompanhamento dedicado, e trate roteamento baseado em domínio mais ACLs como tópicos separados em vez de apressá-los para esta primeira instalação.

end

Quando estiver pronto para mais de um backend, o mesmo padrão se torna visivelmente significativo:

backend app_backend
    balance roundrobin
    server app1 app1:8080 check
    server app2 app2:8080 check

Para edições seguras de uma config bind-mounted, valide primeiro e depois recarregue HAProxy gracefully:

docker compose up -d demo
docker compose run --rm --no-deps haproxy haproxy -V -c -f /usr/local/etc/haproxy/haproxy.cfg
docker compose kill -s HUP haproxy

📝 Nota: A página de stats é intencionalmente local-only neste guia. Se alguma vez a expuser publicamente, adicione autenticação e controles de acesso primeiro.

Isso o traz de volta ao problema original: você queria uma porta frontal limpa na frente de um serviço, sem transformar a primeira configuração em um projeto de operações completo. Você agora tem esse caminho funcionando. Mais importante ainda, você também tem o modelo mental correto: HAProxy recebe o tráfego primeiro, o encaminha para onde pertence, e lhe dá uma forma mais limpa de crescer a stack em uma VPS auto-gerenciada sem perder o controle da configuração.