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 que está 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 à 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 HAProxy É Importante Antes de Você Precisar Dele

Imagine um pequeno 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 todos para a mesma camada ausente: um ponto de entrada controlado entre a internet e seu aplicativo. HAProxy fornece essa camada. Os clientes se conectam ao HAProxy primeiro, e o HAProxy decide para onde cada solicitação vai a seguir.

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 ciente 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 com confiança uma primeira implantação do HAProxy. A tabela abaixo cobre os termos que importam neste guia.

TermoSignificado em linguagem simples
🌐 reverse proxyUm serviço voltado para o cliente 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 em seguida.
❤️ 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 em seguida. 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 imaginar a sua stack como um edifício de escritórios, HAProxy é a receção: o tráfego chega lá primeiro, é direcionado para a sala certa, e deixa de ser enviado para uma sala que está claramente indisponível.

Neste guia, isso traduz-se em três tarefas relevantes para principiantes:

  1. aceitar pedidos HTTP recebidos
  2. encaminhá-los para o backend de demonstração
  3. monitorizar se esse backend está saudável o suficiente para continuar a receber tráfego

Isto já é útil com um backend porque lhe dá uma borda pública controlada em frente da aplicação.

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

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

buildingsetup

Antes de criar arquivos, ajuda ver a forma final da stack. O deployment 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 instalação inicial 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 do 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 bind-mounted 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 você tem estes conceitos 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 manter o foco no 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á 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ê ver nginx, apache2, caddy ou outro serviço já escutando lá, corrija isso primeiro. É uma etapa de pré-voo 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 implantaçã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 implantação limpa:

Configuração do ComposePor que está aqui
hashicorp/http-echo:1.0Fornece 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-stoppedFornece 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 fornece DNS de nome de serviço dentro do projeto, e é 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 do 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 ligação de contentores em vigor, o 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 registo amiga do contentor porque o Docker pode expor stdout facilmente, e mode http em defaults mantém o exemplo inteiro em modo HTTP para que o comportamento do listener e do backend permaneçam consistentes e legíveis.

✏️ NOTA: Um detalhe vale a pena destacar antes da análise da secção: balance roundrobin é definido explicitamente porque as 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 secção:

SecçãoLinhas-chaveO que faz
globallog stdout format raw local0Envia registos para stdout para que o registo 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 liga-o à definição do backend.
backend demo_backendbalance roundrobin, server demo1 demo:5678 checkDiz ao HAProxy qual serviço usar e para monitorizar a sua saúde.
frontend statsbind :8404, stats enable, stats uri /statsAdiciona uma página de validação local opcional para que possa ver o estado de execução mais tarde.

Pode notar uma coisa em falta: option forwardfor. Esta omissão é intencional no caminho base. Preservar o IP do cliente original é útil mais tarde, mas este primeiro deployment é sobre provar o encaminhamento e a saúde do backend, não sobre ensinar comportamento de cabeçalho com um contentor de demonstração que não torna esse sinal especialmente valioso.

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

Execute a validação a partir 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, já provou que o HAProxy pode analisar o ficheiro corretamente e resolver o alvo do backend antes de qualquer listener ao vivo iniciar.

Inicie a Stack e Prove que o Proxy Funciona

Após a validação da configuração, inicie a stack em modo detached:

Como a etapa 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

Em seguida, verifique se ambos os containers estão ativos:

docker compose ps

compose-status

Essa visualização de processo é 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. A próxima requisição verifica o caminho de dados real.

Agora execute o teste de roteamento real a partir do 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 concentre-se na frase do corpo mais do que na formatação exata.

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

browser-valid

Para uma segunda superfície de validação, verifique a página de estatísticas local apenas do VPS:

curl http://127.0.0.1:8404/stats

Na página de estatísticas, 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 última verificação como L4OK in 0ms. Também tenha em mente uma pequena nuance do Docker: depends_on de 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 configuração está errada.

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

EstadoO que isso lhe diz
Containers estão em execuçãoDocker iniciou os processos.
curl -i http://127.0.0.1 retorna 200 OK e a frase de demonstraçãoHAProxy está realmente roteando tráfego para o backend.
Página de estatísticas 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ê altera 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 a 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ê alterou 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: Altere 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 também se aplica 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 no 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: Altere uma coisa de cada vez. Se editar compose.yaml e haproxy.cfg às cegas, torna muito mais difícil dizer 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 funciona, 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 nesta 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 apenas local 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 de entrada limpa na frente de um serviço, sem transformar a primeira configuração em um projeto de operações completo. 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 oferece uma forma mais limpa de crescer a stack em um VPS auto-gerenciado sem perder o controle da configuração.