HAPROXY

Configuração e Customização HAPROXY

Configuração e Customização HAPROXY

2 Ways to Enable Sticky Sessions in HAProxy (Guide)

Link: https://www.haproxy.com/blog/enable-sticky-sessions-in-haproxy

HyperText Transfer Protocol (HTTP), the protocol that defines the language browsers use to communicate with web servers, is stateless, meaning that after you make a web request and a server sends back a response, no memory of that interaction remains. Websites need other ways to remember previous user interactions to make anything more sophisticated than a static web page work.

These days, Javascript frameworks like Vue.js, React.js, and others let developers create single-page applications (SPAs) that provide statefulness to the otherwise stateless web. Because they’re implemented as Javascript applications running in the user’s browser, they can keep track of what the user has done and render the app in a way that accounts for that shared history. However, the user’s browser 

Nick creates technical content for HAProxy Technologies ranging from documentation and blog posts to Wikipedia articles, GitHub READMEs and Stack Overflow answers. With a background in web development and DevOps, he has fun digging into product features and discovering the optimal path for a new blog tutorial.


Configuração e Customização HAPROXY

HAPROXY com persistência de URL

Informações geradas pelo ChatGPT.

Sim, é possível configurar o HAProxy para atender tanto HTTP (porta 80) quanto HTTPS (porta 443) ao mesmo tempo. Isso pode ser feito configurando dois frontends separados — um para HTTP e outro para HTTPS — e ambos encaminhando as requisições para o mesmo backend, de modo que o balanceamento de carga e a persistência por URL sejam aplicados de maneira uniforme para ambos os protocolos.

Exemplo de Configuração para HTTP e HTTPS ao Mesmo Tempo

Aqui está um exemplo de configuração onde o HAProxy aceita tráfego HTTP e HTTPS e roteia as requisições para o mesmo backend, mantendo a persistência baseada na URL para ambos os protocolos:

haproxy
global
    log /dev/log local0
    log /dev/log local1
    notice maxconn 2000

defaults
     log global
     option httplog
     option dontlognull
     timeout connect 5000ms
     timeout client 50000ms
     timeout server 50000ms

# Frontend HTTP (porta 80)
frontend http_front
     bind *:80 
     acl is_http_request path_reg ^/.* # Captura qualquer URL
     use_backend default_backend if is_http_request

# Frontend HTTPS (porta 443)
frontend https_front
     bind *:443 ssl crt /etc/ssl/certs/meucertificado.pem # Certificado SSL
    acl is_https_request path_reg ^/.* # Captura qualquer URL
    use_backend default_backend if is_https_request

# Backend
     backend default_backend
     balance roundrobin 
   stick-table type string size 200k expire 30m store gpc0
    stick on url_param(url) # Persistência baseada na URL
    cookie SERVERID insert indirect nocache
    server server1 192.168.1.1:80 check # Servidor HTTP
    server server2 192.168.1.2:80 check # Servidor HTTP
    server server3 192.168.1.3:80 check # Servidor HTTP 

Explicação da Configuração:

  1. Frontend HTTP:

    • bind *:80: O frontend escuta na porta 80 para tráfego HTTP.

    • acl is_http_request path_reg ^/.*: A ACL captura qualquer URL para redirecioná-la para o backend.

    • use_backend default_backend if is_http_request: Se a requisição for HTTP, ela é direcionada para o default_backend.

  2. Frontend HTTPS:

    • bind *:443 ssl crt /etc/ssl/certs/meucertificado.pem: Este frontend escuta na porta 443 para tráfego HTTPS e usa o certificado SSL fornecido no arquivo /etc/ssl/certs/meucertificado.pem.

    • acl is_https_request path_reg ^/.*: A ACL captura qualquer URL, assim como no frontend HTTP.

    • use_backend default_backend if is_https_request: Se a requisição for HTTPS, ela é direcionada para o default_backend.

  3. Backend:

    • O backend é compartilhado entre ambos os frontends HTTP e HTTPS, com persistência baseada na URL usando o stick-table para garantir que as requisições para a mesma URL sejam sempre roteadas para o mesmo servidor.

    • cookie SERVERID insert indirect nocache: Garante a persistência usando cookies.

    • Os servidores backend continuam na porta 80 (HTTP), porque o HAProxy está fazendo a terminação SSL.

Como Funciona:

  1. Requisição HTTP:

    • O cliente acessa a URL usando http://meusite.com/pagina1.

    • O HAProxy recebe a requisição na porta 80 e a encaminha para um dos servidores backend (server1, server2, server3), com base no balanceamento de carga roundrobin.

    • O servidor backend responde, e o HAProxy registra a URL /pagina1 e o servidor que a atendeu.

  2. Requisição HTTPS:

    • O cliente acessa a URL usando https://meusite.com/pagina1.

    • O HAProxy recebe a requisição na porta 443, faz a descriptografia SSL e encaminha para o mesmo backend (porta 80), utilizando o mesmo servidor que atendeu a primeira requisição HTTP para aquela URL.

    • O HAProxy verifica a tabela de stickiness e direciona a requisição para o mesmo servidor que atendeu a primeira requisição, mantendo a persistência.

  3. Persistência para Todos os Usuários:

    • A persistência é mantida independentemente de ser uma requisição HTTP ou HTTPS, porque a persistência está baseada na URL (stick on url_param(url)), não em cookies ou IP do cliente.

    • Todos os usuários que acessarem a mesma URL (seja por HTTP ou HTTPS) serão direcionados para o mesmo servidor backend que atendeu a primeira requisição para aquela URL.

Certificado SSL:

O caminho /etc/ssl/certs/meucertificado.pem deve apontar para o certificado SSL e a chave privada do seu domínio. Se você estiver usando o Let's Encrypt ou outra autoridade certificadora (CA), basta colocar o arquivo .pem correto que contenha o certificado público e a chave privada.

Caso você precise gerar um certificado SSL autoassinado, pode usar o seguinte comando openssl:

bash
openssl req -x509 -newkey rsa:2048 -keyout /etc/ssl/private/meuchave.key -out /etc/ssl/certs/meucertificado.pem -days 365

Esse comando gera um certificado autoassinado, o que é útil para testes ou ambientes internos, mas para produção, recomenda-se o uso de um certificado de uma autoridade certificadora (CA) confiável.


Conclusão:

  • Sim, o HAProxy pode atender tanto HTTP quanto HTTPS ao mesmo tempo, com a mesma configuração de persistência por URL para ambos os protocolos.

  • A configuração utiliza dois frontends separados (um para HTTP e outro para HTTPS), mas ambos encaminham as requisições para o mesmo backend, garantindo que a persistência de URL seja aplicada de forma consistente, independentemente do protocolo.

  • A terminação SSL acontece no HAProxy, o que significa que ele descriptografa as requisições HTTPS e as envia como HTTP para os servidores backend.


Se você deseja configurar o HAProxy para rotear tráfego em portas diferentes de 80 (HTTP) e 443 (HTTPS), o procedimento é semelhante, mas você deve ajustar a configuração de frontends e backends para escutar nas portas específicas que deseja utilizar.

A lógica de balanceamento de carga e persistência por URL será a mesma, mas em vez de usar as portas padrão (80 e 443), você configurará o HAProxy para escutar nas portas que você escolher.

Exemplo de Configuração para Portas Diferentes:

Vamos imaginar que você deseja usar as portas 8080 para HTTP e 8443 para HTTPS, em vez das portas padrão (80 e 443). A configuração seria:

global
    log /dev/log local0
    log /dev/log local1 notice
    maxconn 2000

defaults
    log     global
    option  httplog
    option  dontlognull
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms

# Frontend para HTTP (porta 8080)
frontend http_front
    bind *:8080  # Escutando na porta 8080
    acl is_http_request path_reg ^/.*  # Captura qualquer URL
    use_backend default_backend if is_http_request

# Frontend para HTTPS (porta 8443)
frontend https_front
    bind *:8443 ssl crt /etc/ssl/certs/meucertificado.pem  # Certificado SSL
    acl is_https_request path_reg ^/.*  # Captura qualquer URL
    use_backend default_backend if is_https_request

# Backend
backend default_backend
    balance roundrobin
    stick-table type string size 200k expire 30m store gpc0
    stick on url_param(url)  # Persistência baseada na URL
    server server1 192.168.1.1:80 check  # Servidor HTTP
    server server2 192.168.1.2:80 check  # Servidor HTTP
    server server3 192.168.1.3:80 check  # Servidor HTTP

Explicação das Modificações:

  1. Frontend HTTP:

    • bind *:8080: O HAProxy agora escuta na porta 8080 para tráfego HTTP, em vez de 80.

    • acl is_http_request path_reg ^/.*: A regra ACL captura qualquer URL que for solicitada e a redireciona para o backend.

  2. Frontend HTTPS:

    • bind *:8443 ssl crt /etc/ssl/certs/meucertificado.pem: O HAProxy escuta na porta 8443 para tráfego HTTPS e usa o certificado SSL localizado no caminho /etc/ssl/certs/meucertificado.pem. O certificado SSL deve ser válido, seja autoassinado ou de uma autoridade certificadora.

  3. Backend:

    • A configuração do backend permanece a mesma, com balanceamento de carga baseado em roundrobin, persistência por URL usando stick-table, e a inserção do cookie SERVERID para garantir a persistência.

  4. Servidores Backend:

    • server server1 192.168.1.1:80 check: Os servidores backend continuam sendo configurados na porta 80, porque o HAProxy irá fazer a terminação SSL para o tráfego HTTPS e, em seguida, encaminhá-lo para os servidores backend na porta 80.

Fluxo de Funcionamento:

1. Requisição HTTP (porta 8080):

2. Requisição HTTPS (porta 8443):

3. Persistência para Todos os Usuários:


Caso Você Queira Usar Portas Diferentes para Cada Backend:

Se você quiser que o tráfego seja roteado para diferentes portas nos servidores backend, você pode ajustar a configuração para cada servidor backend. Por exemplo, se você tiver servidores que escutam em portas diferentes, a configuração seria algo como:

backend default_backend
    balance roundrobin
    stick-table type string size 200k expire 30m store gpc0
    stick on url_param(url)
    cookie SERVERID insert indirect nocache
    server server1 192.168.1.1:8081 check  # Servidor backend escutando na porta 8081
    server server2 192.168.1.2:8082 check  # Servidor backend escutando na porta 8082
    server server3 192.168.1.3:8083 check  # Servidor backend escutando na porta 8083

Essa configuração faria com que cada servidor backend estivesse escutando em portas diferentes, mas o HAProxy ainda aplicaria a persistência e o balanceamento de carga.

Resumo:

Configuração e Customização HAPROXY

Building a High Availability Cluster with HAProxy, Keepalived, and Docker: A Step-by-Step Guide

Link: https://medium.com/@yahyasghiouri1998/building-a-high-availability-cluster-with-haproxy-keepalived-and-docker-a-step-by-step-guide-9325f4ac8aa7

Aug 30, 2024
High availability

High availability (HA) is essential for ensuring that web applications remain accessible, even in the face of hardware or software failures. An HA architecture distributes traffic across multiple servers, preventing any single point of failure from disrupting service. In this article, we’ll explore how to build a high availability cluster using HAProxy and Keepalived, two powerful tools for load balancing and failover.

To enhance flexibility and simplify deployment, we’ll leverage Docker to containerize HAProxy, Keepalived, and our web applications. Docker allows us to create a portable and easily manageable HA setup that can be deployed across different environments, whether on-premises or in the cloud.

Throughout this guide, we’ll walk you through the entire process — from setting up Docker networks and building Dockerfiles to configuring HAProxy and Keepalived for seamless failover. By the end, you’ll have a fully functional HA cluster that ensures your web applications are always available, all within a Dockerized environment.

I-/ General Concepts

Before diving into the different configurations, it’s helpful to understand the core components of the architecture.

I-1/HAproxy

HAProxy, as its name suggests, stands for High Availability Proxy. It is a robust and versatile tool designed to provide high availability and efficient load balancing for network traffic.

HAProxy is a widely used tool for distributing incoming requests across multiple backend servers to enhance both reliability and performance. It performs continuous health checks on these servers to ensure that traffic is routed only to those that are healthy and responsive.

The tool employs various algorithms, such as round-robin and least connections, to effectively balance the load. Supporting both TCP and HTTP traffic, HAProxy operates at Layer 4 (the transport layer) and Layer 7 (the application layer) of the OSI model.

There are two main components when configuring HAproxy , a frontend and a backend section.

  • Frontend section: It is the entry point for incoming client requests. It defines how HAProxy listens for incoming traffic and how it should handle these requests, here we specify the address and port on which HAProxy should listen, as well as any rules or conditions for routing the traffic to the appropriate backend by inspecting the incoming packets.
  • Backend section: it represents the servers that will handle the requests forwarded by the frontend. we define how HAProxy should route traffic to the backend servers and how it should manage these servers basically we specify also load balancing algorithms, and health checks. In summary we control how requests will be distributed among the servers and how we are going to handle server failures or maintenance.
HA proxy load balancer

I-2/Keepalived & VRRP

VRRP (Virtual Router Redundancy Protocol) is designed to create a virtual router that represents a group of physical routers, allowing them to work together to present a single virtual IP address (VIP) to the network. This VIP is used as the default gateway by clients.

In a VRRP setup, one router is elected as the master. The master router handles traffic directed to the VIP, while the other routers in the group act as backups and monitor the master router’s health. If the master router fails, one of the backup routers takes over as the new master, ensuring the continuity of service.

Keepalived is a widely used implementation of VRRP with additional features. It assigns a priority to each node in the group, and based on these priorities, it elects a new master if a failure occurs. Keepalived enhances VRRP with advanced health checks and failover capabilities, making it ideal for high-availability setups.

Virtual IP assignment

II-/ Deployment architecture

After understanding the foundational concepts of HAProxy and Keepalived, it’s crucial to see how these components come together to form a high availability cluster.

Deployment Architecture
Deployment architecture

The architecture I’ve implemented leverages Docker to create a resilient and scalable environment, ensuring continuous service availability. The visual representation above illustrates how traffic is routed through HAProxy instances and managed by Keepalived to provide redundancy and failover capabilities.

To interconnect all components, I set up a Docker bridge network, which ensures seamless communication between the HAProxy instances, Keepalived, and the backend servers. This network allows the HAProxy instances to effectively distribute incoming traffic across multiple backend servers while monitoring their health and performance.

In this setup, there is a primary HAProxy instance (the master) and a secondary instance (the backup) ready to take over if the master fails. Keepalived, installed on both machines, manages the virtual IP (VIP) that clients connect to. This VIP ensures that, even in the event of a failure, traffic is automatically redirected to the backup HAProxy instance, maintaining service availability without interruption.

The backend comprises three cloned instances of a server running a simple Flask application that serves static content. This setup is an example of a stateless application deployment, where each instance operates independently without relying on session persistence or shared state. In the case of stateful applications, additional architectural considerations would be necessary, such as implementing shared storage, session replication, sticky sessions, or database clustering to ensure consistency and availability. Following best practices in system design is crucial to address these challenges and optimize the architecture based on the application’s specific requirements and context.

III-/Step by step guide

  • The first thing we’re going to do is create our stateless app a simple Python application that doesn’t store any session information. To get started, we need to create a virtual environment, so make sure you have Python installed on your machine.
Virtual environment creation
  • Activate the virtual environment, and then install Flask.
Installing Flask
  • Now Flask is installed in our virtual environment, we are going to create a simple Flask App with hello world!content, for me I’ll use nano editor, you can use whatever editor you want for that purpose.
nano app.py
Flask webapp

Copy paste the following content or create your own:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello, World!'

if __name__ == '__main__':
app.run(debug=False)

Flask apps run by default in port 5000, you can test the webapp by running: python app.py

Running Flask app
Accessing web app on the browser

The app is up and running Now we should get the dependencies used in our app, we will save them on requirements.txt .

Saving requirements in a file
pip freeze > requirements.txt

- We will need these requirements so we can create the Dockerfile of our webapp, then run the following command to create a Dockerfile of the webapp.

nano Dockerfile.webapp

copy and paste the following:


FROM python:3.12.5
Expose 5000
ENV FLASK_app=app.py
WORKDIR /app
COPY ./app.py .
COPY ./requirements.txt .
RUN pip install -r requirements.txt
RUN pip install gunicorn
CMD gunicorn -w 4 -b :5000 app:app

Note that we added Gunicorn in our Dockerfile to run our Python web app because using development servers is not suitable for production environments.

Let’s create our first image , it’ll be saved locally.

docker build -f Dockerfile.webapp -t webapp_test .

After finalizing the Dockerfile for our web app, it’s time to create our Docker Compose YAML file, which will define our entire architecture. We’ll break it down step by step.

Here is the docker compose file.

version: '3.8'

services:
haproxy1:
build:
context: .
dockerfile: Dockerfile
container_name: haproxy1
networks:
yahya_prive:
ipv4_address: 10.0.0.150
cap_add:
- NET_ADMIN
ports:
- "8888:80"
- "8404:8404"
volumes:
- C:\Users\John macmillan\Desktop\python_project\haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- C:\Users\John macmillan\Desktop\python_project\keepalived_primary.conf:/etc/keepalived/keepalived.conf:ro
depends_on:
- web1
- web2
- web3
entrypoint: ["/bin/sh", "-c", "keepalived -D -f /etc/keepalived/keepalived.conf && haproxy -f /usr/local/etc/haproxy/haproxy.cfg"]

haproxy2:
build:
context: .
dockerfile: Dockerfile
container_name: haproxy2
networks:
yahya_prive:
ipv4_address: 10.0.0.155
cap_add:
- NET_ADMIN
ports:
- "8800:80"
- "8405:8404"
volumes:
- C:\Users\John macmillan\Desktop\python_project\haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- C:\Users\John macmillan\Desktop\python_project\keepalived_bck.conf:/etc/keepalived/keepalived.conf:ro
depends_on:
- web1
- web2
- web3
entrypoint: ["/bin/sh", "-c", "keepalived -D -f /etc/keepalived/keepalived.conf && haproxy -f /usr/local/etc/haproxy/haproxy.cfg"]

web1:
image: webapp_test
container_name: web1
networks:
- yahya_prive

web2:
image: webapp_test
container_name: web2
networks:
- yahya_prive

web3:
image: webapp_test
container_name: web3
networks:
- yahya_prive

networks:
yahya_prive:
driver: bridge
#specify the driver
ipam:
config :
- subnet: 10.0.0.0/24
gateway: 10.0.0.1

let’s break this down:

First thing we did is to create a network bridge . This Network bridge is called yahya_privethen we specified the CIDR notation: 10.0.0.0/24with the following gateway: 10.0.0.1

it’ll be our private network in which all the containers will be assigned an ip address from the ip address range 10.0.0.0/24 .

networks:
yahya_prive:
driver: bridge
#specify the driver
ipam:
config :
- subnet: 10.0.0.0/24
gateway: 10.0.0.1

It’s advisable to use a custom network rather than the default network provided by Docker Compose. This approach enhances security and allows you to use domain names instead of IP addresses in configurations.

Then there is a section for our webapps, they’re called respectively: web1, web2 and web3, all three of them is now attached to yahya_privenetwork.

Each one was provided a name, and the base image was created previously, and it was saved locally which is webapp_test

web1:
image: webapp_test
container_name: web1
networks:
- yahya_prive

web2:
image: webapp_test
container_name: web2
networks:
- yahya_prive

web3:
image: webapp_test
container_name: web3
networks:
- yahya_prive

After this we’ve created the service for our HAProxy load balancer.

haproxy1:
build:
context: .
dockerfile: Dockerfile
container_name: haproxy1
networks:
yahya_prive:
ipv4_address: 10.0.0.150
cap_add:
- NET_ADMIN
ports:
- "8888:80"
- "8404:8404"
volumes:
- C:\Users\John macmillan\Desktop\python_project\haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- C:\Users\John macmillan\Desktop\python_project\keepalived_primary.conf:/etc/keepalived/keepalived.conf:ro
depends_on:
- web1
- web2
- web3
entrypoint: ["/bin/sh", "-c", "keepalived -D -f /etc/keepalived/keepalived.conf && haproxy -f /usr/local/etc/haproxy/haproxy.cfg"]

The Master HAProxy is called haproxy1, and it was assigned the ip address:

10.0.0.150from the private network yahya_prive.

To enable Keepalived, which uses VRRP for failover, the container requires additional network capabilities. Therefore, we grant the container NET_ADMIN privileges, allowing it to manage network settings necessary for VRRP operations.

The necessary configuration files for HAProxy and Keepalived are mounted as read-only volumes from the host machine to ensure that both services are properly configured.

The entrypoint directive ensures that Keepalived starts in the background and monitors the HAProxy service, providing the high availability setup.

And obviously, there is the configuration Dockerfile that contains our Keepalived and HAProxy.

FROM ubuntu:22.04

# Install Keepalived and HAProxy
RUN apt-get update && apt-get install -y \
nano \
net-tools \
keepalived \
haproxy

EXPOSE 80
EXPOSE 8444

The configuration for both load balancers is exactly the same (haproxy.cfg)

global
stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
log stdout format raw local0 info

defaults
mode http
timeout client 10s
timeout connect 5s
timeout server 10s
timeout http-request 10s
log global

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

frontend myfrontend
bind :80
default_backend webservers

backend webservers
server s1 web1:5000 check
server s2 web2:5000 check
server s3 web3:5000 check

What we’ve done here is configure our load balancer to listen for requests on port 80. We’ve also defined our web servers in the backend webservers section, allowing us to route traffic to them effectively.

On the other hand, we had different configurations of Keepalived daemons for both nodes.

here is the configuration for the master node (keepalived_primary.conf):

vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 33
priority 255
advert_int 1
unicast_src_ip 10.0.0.50

authentication {
auth_type PASS
auth_pass letmein
}

virtual_ipaddress {
10.0.0.50/24 dev eth0
}
}

This is a basic configuration where we’ve assigned a priority of 255, which is higher than the priority set on the backup machine. As a result, this machine will be assigned the virtual IP address first. We’ve defined the state as MASTER for this machine and specified eth0 as the interface, as it’s connected to the private network through this interface.

The most critical part of this configuration is the virtual_ipaddress section, where we define the virtual IP address (10.0.0.50/24) that will be managed by the VRRP protocol. This IP address will be assigned to the master machine, ensuring that it handles traffic as long as it remains in the master state. The authentication section provides basic security by requiring a password for VRRP communications, adding an extra layer of protection to the setup.

The configuration for the backup node will be different a little bit (keepalived_bck.conf):

vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 33
priority 150
advert_int 1
unicast_src_ip 10.0.0.50

authentication {
auth_type PASS
auth_pass letmein
}

virtual_ipaddress {
10.0.0.50/24 dev eth0
}
}

We’ve set a priority of 150, which is lower than that of the master, and designated the state as BACKUP. Both the master and backup nodes share the same virtual IP address (VIP). In the event of the master node failing, the backup node will detect this through ARP checks and automatically take over the VIP, ensuring continued service availability.

Note that the Docker Compose file includes a depends_on section that specifies the order in which containers are started. In this case:

depends_on:
- web1
- web2
- web3

This configuration ensures that the web applications (web1web2, and web3) start before the load balancers are initialized. This order is crucial to ensure that the web servers are up and running before the load balancers begin routing traffic to them.

After completing the necessary configurations, you can run the entire setup with the following command:

docker-compose -p high_availability_cluster up -d

Now, your setup is up and running.

Accessing webapp
Accessing webapp

The haproxy1 container will receive the virtual IP address on its eth0 interface. You can verify this by running the following command inside the container: ip a.

Virtual Ip address assigned

We can try sending an HTTP request using the curl command from a node inside the yahya_prive network. For example, we can use web1 for this purpose.

Getting web content from using VIP

IV-/Conclusion

In conclusion, building a high availability cluster with HAProxy, Keepalived, and Docker is an effective way to ensure continuous service availability and reliability. Through this guide, we’ve explored the fundamental concepts of high availability, examined how HAProxy and Keepalived work together to manage traffic and failover, and demonstrated how to set up this architecture in a Docker environment. By following these steps, you can create a resilient infrastructure that can handle disruptions and maintain service continuity, making it an essential setup for any robust and scalable application deployment.

Equipped with this understanding, you’ll now be able to enhance your network infrastructure and deploy more resilient, scalable applications with confidence.

We invite you to share your experiences and insights in the comments below. We’re eager to hear your feedback and thoughts. Happy networking!

References

For more detailed information :

Configuração e Customização HAPROXY

Configuração de URL Path no HAPROXY

Arquivo exemplo haproxy.cfg

global
    log /dev/log local0
#    log 127.0.0.1 local0 info
    daemon
    log stdout format raw local0
    maxconn 2048
    user haproxy
    group haproxy

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms
    retries 3

listen stats
    bind *:1120
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:senha123


######################################
# FRONTEND 1 – porta 2023
######################################
frontend http_front_2023
    bind *:2023
    default_backend doc_backend_2023

######################################
# FRONTEND 2 – porta 2024
######################################
frontend http_front_2024
    bind *:2024
    default_backend doc_backend_2024

######################################
# FRONTEND 3 – porta 2025
######################################
frontend http_front_2025
    bind *:2025
    default_backend doc_backend_2025

######################################
# BACKEND 1 – para frontend 2023
######################################
backend doc_backend_2023
    balance roundrobin
    stick-table type string len 64 size 100k expire 1h store server_id
    stick on path       # registra somente o /teste
#  stick on concat(req.hdr(host), path) - entrada para registrar url e /teste
#  stick on concat(concat(req.hdr(host), path), concat("?", query))  - entrada para registrar  url e /teste?normal (query)

    server srv1_2023 192.168.0.101:2023 check
    server srv2_2023 192.168.0.102:2023 check
    server srv3_2023 192.168.0.103:2023 check

######################################
# BACKEND 2 – para frontend 2024
######################################
backend doc_backend_2024
    balance roundrobin
    stick-table type string len 64 size 100k expire 1h store server_id
    stick on path       # registra somente o /teste
#  stick on concat(req.hdr(host), path) - entrada para registrar url e /teste
#  stick on concat(concat(req.hdr(host), path), concat("?", query))  - entrada para registrar  url e /teste?normal (query)

    server srv1_2024 192.168.0.104:2024 check
    server srv2_2024 192.168.0.105:2024 check
    server srv3_2024 192.168.0.106:2024 check

######################################
# BACKEND 3 – para frontend 2025
######################################
backend doc_backend_2025
    balance roundrobin
    stick-table type string len 64 size 100k expire 1h store server_id
    stick on path       # registra somente o /teste
#  stick on concat(req.hdr(host), path) - entrada para registrar url e /teste
#  stick on concat(concat(req.hdr(host), path), concat("?", query))  - entrada para registrar  url e /teste?normal (query)

    server srv1_2025 192.168.0.107:2025 check
    server srv2_2025 192.168.0.108:2025 check
    server srv3_2025 192.168.0.109:2025 check


Configuração e Customização HAPROXY

Configuração de logs no HAPROXY

ChatGPT:
Ótimo! Vamos configurar o HAProxy + rsyslog dentro (ou fora) do Docker para gerar logs em horário local, salvos no arquivo /var/log/haproxy.log.


🧱 O que vamos fazer:

  1. Configurar o HAProxy para enviar logs ao syslog (/dev/log)

  2. Garantir que o rsyslog esteja ativo no host

  3. Mapear o socket /dev/log para o container Docker (ou fazer logging fora)

  4. Salvar os logs com horário local no host


✅ 1. Configuração do HAProxy (haproxy.cfg)

Altere a seção global do seu haproxy.cfg para:

global log /dev/log local0 info daemon maxconn 2048 user haproxy group haproxy

defaults log global mode http option httplog option dontlognull timeout connect 5000ms timeout client 50000ms timeout server 50000ms

✅ 2. Configurar o rsyslog no host Linux

Verifique se o rsyslog está ativo:

sudo systemctl status rsyslog 

Se não estiver, ative:

sudo systemctl enable --now rsyslog

Crie o arquivo de log e a regra:

sudo touch /var/log/haproxy.log sudo chown syslog:adm /var/log/haproxy.log

Agora crie um arquivo de configuração para o rsyslog:

sudo nano /etc/rsyslog.d/49-haproxy.conf

E adicione:

local0.* /var/log/haproxy.log

Reinicie o rsyslog:

sudo systemctl restart rsyslog

✅ 3. Rodar o container HAProxy com acesso ao /dev/log

Você precisa montar o socket do syslog no container:

👉 Exemplo com docker run:

bash
docker run -d \ --name haproxy-logs \ -v $(pwd)/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro \ -v /dev/log:/dev/log \ -p 2025:2025 \ haproxy:2.9

✅ O -v /dev/log:/dev/log é essencial — ele conecta o HAProxy ao rsyslog do host.

👉 Exemplo com docker-compose.yml:


services: haproxy: image: haproxy:2.9 volumes:   - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro   - /dev/log:/dev/log ports:   - "2025:2025"

✅ 4. Verificar os logs

Após acessar HAProxy (ex: curl http://localhost:2025/teste), veja os logs com:

tail -f /var/log/haproxy.log

O horário será o local do host, por exemplo:

Jul 18 10:08:27 haproxy-logs haproxy[1]: 192.168.0.10:42839 [18/Jul/2025:10:08:27.315] http_front doc_backend ...

🧪 Dica extra: usar hostname no log

Se quiser que apareça o nome do container no log, passe -h haproxy-logs no docker run, ou use no docker-compose.yml:

hostname: haproxy-logs

🚀 Pronto!

Agora o HAProxy está:

Configuração e Customização HAPROXY

Reconfiguração automática do haproxy.cfg do HAPROXY

ChatGPT:

Perfeito! Aqui está um script cron completo e seguro para fazer o reload do haproxy.cfg em todos os containers haproxy do Swarm, sem reiniciar os containers — apenas recarregando o processo haproxy com kill -HUP.

✅ Script: reload-haproxy-containers.sh

bash
## INICIO SCRIPT ##
#!/bin/bash
# Nome da imagem usada no serviço haproxy
IMAGE_NAME="haproxytech/haproxy-debian:3.3"
# Comando de reload usado dentro do container
RELOAD_CMD="haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg && kill -HUP 1"
# Busca containers que usam a imagem especificada
CONTAINERS=$(docker ps --filter "ancestor=$IMAGE_NAME" --format "{{.ID}}")

if [ -z "$CONTAINERS" ]; then
    echo "[INFO] Nenhum container HAProxy em execução com imagem '$IMAGE_NAME'"
    exit 0
fi
echo "[INFO] Recarregando configuração HAProxy em $(echo "$CONTAINERS" | wc -l) container(s)..."
for cid in $CONTAINERS; do
    echo " → Validando e recarregando HAProxy no container $cid..."
    docker exec "$cid" sh -c "$RELOAD_CMD" && \
        echo " ✅ Container $cid recarregado com sucesso." || \
        echo " ❌ Erro ao recarregar o container $cid."
done
## FIM SCRIPT ##
🔧 Como usar
1. Salve o script
sudo mkdir -p /usr/local/bin
sudo nano /usr/local/bin/reload-haproxy-containers.sh
Cole o conteúdo, salve, e depois:
sudo chmod +x /usr/local/bin/reload-haproxy-containers.sh
2. Agende via crontab
Edite o cron para o usuário que gerencia o Swarm (geralmente root):
sudo crontab -e
Adicione a linha para executar de hora em hora:
0 * * * * /usr/local/bin/reload-haproxy-containers.sh >> /var/log/reload-haproxy.log 2>&1
🛡️ Segurança adicional (opcional)
Se quiser ser ainda mais seletivo, você pode filtrar por nome do serviço ou label, ex:
docker ps --filter "name=mystack_haproxy" --format "{{.ID}}"
Ou com label:
docker ps --filter "label=com.docker.stack.namespace=mystack" --format "{{.ID}}"
✅ Resultado
Com isso, seu Swarm:

✅ Executará reload leve e seguro do haproxy.cfg de hora em hora

✅ Sem precisar redeploy, sem downtime

✅ Sincronizado via GlusterFS automaticamente

✅ Sem scripts dentro dos containers
Configuração e Customização HAPROXY

Reconfiguração automática do haproxy.cfg do HAPROXY - 2

chatGPT

 

Perfeito! Abaixo está um script que monitora alterações no arquivo haproxy.cfg via inotify e executa um reload automático nos containers HAProxy quando detectar mudanças — ideal para quem está usando GlusterFS com bind mount no Docker Swarm.

✅ Objetivo
Monitorar:

bash
/opt/aplicativos/haproxy/haproxy.cfg
Quando houver qualquer modificação, o script:

Valida a nova configuração com haproxy -c

Executa kill -HUP 1 no processo do HAProxy dentro de cada container ativo

✅ Pré-requisitos
Instale o inotify-tools no node onde o script vai rodar:
bash
Copiar
Editar
sudo apt install inotify-tools
📜 Script: watch-haproxy-reload.sh
bash
Copiar
Editar
#!/bin/bash

WATCH_FILE="/opt/aplicativos/haproxy/haproxy.cfg"
IMAGE="haproxytech/haproxy-debian:3.3"

echo "[INFO] Monitorando $WATCH_FILE por alterações..."

inotifywait -m -e close_write "$WATCH_FILE" | while read -r path event file; do
    echo "[INFO] Detecção de alteração em $file — iniciando validação e reload..."

    CONTAINERS=$(docker ps --filter "ancestor=$IMAGE" --format "{{.ID}}")

    if [ -z "$CONTAINERS" ]; then
        echo "[WARN] Nenhum container com imagem $IMAGE em execução."
        continue
    fi

    for cid in $CONTAINERS; do
        echo "→ Validando config dentro do container $cid..."
        if docker exec "$cid" haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg; then
            echo "✓ Configuração válida. Recarregando HAProxy no container $cid..."
            docker exec "$cid" kill -HUP 1
            echo "✅ Reload concluído para $cid"
        else
            echo "❌ Configuração inválida. Nenhum reload feito."
        fi
    done
done
✅ Como usar
1. Salve o script
bash
Copiar
Editar
sudo nano /usr/local/bin/watch-haproxy-reload.sh
Cole o conteúdo acima, salve e torne executável:

bash
Copiar
Editar
sudo chmod +x /usr/local/bin/watch-haproxy-reload.sh
2. Execute em background (em 1 só node basta)
bash
Copiar
Editar
nohup /usr/local/bin/watch-haproxy-reload.sh >> /var/log/haproxy-watch.log 2>&1 &
Ou adicione no /etc/rc.local ou systemd para subir automaticamente no boot.

🛡️ Segurança e estabilidade
Use em apenas 1 node do Swarm para evitar reloads duplicados.

O reload é suave (com SIGHUP), não derruba conexões abertas.

Você pode integrar isso com o script cron também, se quiser backup/rollback.

✅ Resumo do que você tem agora:
Item Status
GlusterFS replicando haproxy.cfg ✅
Containers Docker Swarm usando bind mount ✅
Reload automático com inotify ✅
Validação de configuração antes do reload ✅

Instalação HAPROXY docker


Instalação HAPROXY docker

Instalação HAproxy Docker HAproxytec

Link: https://hub.docker.com/r/haproxytech/haproxy-debian

What is HAProxy?

HAProxy is the fastest and most widely used open-source load balancer and application delivery controller. Written in C, it has a reputation for efficient use of both processor and memory. It can proxy at either layer 4 (TCP) or layer 7 (HTTP) and has additional features for inspecting, routing and modifying HTTP messages.

It comes bundled with a web UI, called the HAProxy Stats page, that you can use to monitor error rates, the volume of traffic and latency. Features can be toggled on by updating a single configuration file, which provides a syntax for defining routing rules, rate limiting, access controls, and more.

Other features include:

logo

How to use this image

This image is being shipped with a trivial sample configuration and for any real life use it should be configured according to the extensive documentation⁠ and examples⁠. We will now show how to override shipped haproxy.cfg with one of your own.

Create a Dockerfile

FROM haproxytech/haproxy-debian:3.0
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg

Build the container

$ docker build -t my-haproxy .

Test the configuration file

$ docker run -it --rm my-haproxy haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg

Run the container

$ docker run -d --name my-running-haproxy my-haproxy

You will also need to publish the ports your HAProxy is listening on to the host by specifying the -p option, for example -p 8080:80 to publish port 8080 from the container host to port 80 in the container.

Use volume for configuration persistency

$ docker run -d --name my-running-haproxy -v /path/to/etc/haproxy:/usr/local/etc/haproxy:ro haproxytech/haproxy-debian:3.0

Note that your host's /path/to/etc/haproxy folder should be populated with a file named haproxy.cfg as well as any other accompanying files local to /etc/haproxy.

Reloading config

To be able to reload HAProxy configuration, you can send SIGUSR2 to the container:

$ docker kill -s USR2 my-running-haproxy

Enable Data Plane API

Data Plane API⁠ sidecar is being distributed by default in all 2.0+ images and to enable it there are a few steps required:

  1. define one or more users through userlist
  2. enable dataplane api process through program api
  3. enable haproxy.cfg to be read/write mounted in Docker, either by defining volume being r/w or by rebuilding image with your own haproxy.cfg
  4. expose dataplane TCP port in Docker with --expose

Relevant part of haproxy.cfg is below:

userlist haproxy-dataplaneapi
    user admin insecure-password mypassword

program api
   command /usr/bin/dataplaneapi --host 0.0.0.0 --port 5555 --haproxy-bin /usr/sbin/haproxy --config-file /usr/local/etc/haproxy/haproxy.cfg --reload-cmd "kill -SIGUSR2 1" --restart-cmd "kill -SIGUSR2 1" --reload-delay 5 --userlist haproxy-dataplaneapi
   no option start-on-reload

To run such image we would use the following command (note that volume containing haproxy.cfg is mounted r/w and port tcp/5555 is being exposed):

$ docker run -d --name my-running-haproxy --expose 5555 -v /path/to/etc/haproxy:/usr/local/etc/haproxy:rw haproxytech/haproxy-debian

License

View license information⁠ for the software contained in this image.

As with all Docker images, these likely also contain other software which may be under other licenses (such as Bash, etc from the base distribution, along with any direct or indirect dependencies of the primary software being contained).

Instalação HAPROXY docker

Instalação HAproxy Docker Bitnami

Link: https://github.com/bitnami/containers/tree/main/bitnami/haproxy

HAProxy is a TCP proxy and a HTTP reverse proxy. It supports SSL termination and offloading, TCP and HTTP normalization, traffic regulation, caching and protection against DDoS attacks.

Overview of HAProxy Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement.

docker run --name haproxy bitnami/haproxy:latest

⚠️ Important Notice: Upcoming changes to the Bitnami Catalog

Beginning August 28th, 2025, Bitnami will evolve its public catalog to offer a curated set of hardened, security-focused images under the new Bitnami Secure Images initiative. As part of this transition:

These changes aim to improve the security posture of all Bitnami users by promoting best practices for software supply chain integrity and up-to-date deployments. For more details, visit the Bitnami Secure Images announcement.

Why use Bitnami Images?

Looking to use HAProxy in production? Try VMware Tanzu Application Catalog, the commercial edition of the Bitnami catalog.

Supported tags and respective Dockerfile links

Learn more about the Bitnami tagging policy and the difference between rolling tags and immutable tags in our documentation page.

You can see the equivalence between the different tags by taking a look at the tags-info.yaml file present in the branch folder, i.e bitnami/ASSET/BRANCH/DISTRO/tags-info.yaml.

Subscribe to project updates by watching the bitnami/containers GitHub repo.

Get this image

docker pull bitnami/haproxy:latest

To use a specific version, you can pull a versioned tag. You can view the list of available versions in the Docker Hub Registry.

docker pull bitnami/haproxy:[TAG]

If you wish, you can also build the image yourself by cloning the repository, changing to the directory containing the Dockerfile and executing the docker build command. Remember to replace the APPVERSION and OPERATING-SYSTEM path placeholders in the example command below with the correct values.

git clone https://github.com/bitnami/containers.git
cd bitnami/APP/VERSION/OPERATING-SYSTEM
docker build -t bitnami/APP:latest .

Why use a non-root container?

Non-root container images add an extra layer of security and are generally recommended for production environments. However, because they run as a non-root user, privileged tasks are typically off-limits. Learn more about non-root containers in our docs.

Configuration

Running commands

To run commands inside this container you can use docker run, for example to execute haproxy --version you can follow the example below:

docker run --rm --name haproxy bitnami/haproxy:latest -- --version

In order for the container to work, you need to mount your custom haproxy.cfg file in /bitnami/haproxy/conf/. The following example runs HAProxy with a custom configuration file:

docker run --rm --name haproxy -v /path/to/haproxy.cfg:/bitnami/haproxy/conf/haproxy.cfg bitnami/haproxy:latest

Using docker-compose:

version: '2'
services:

  haproxy:
    image: bitnami/haproxy:latest
    volumes:
      - /path/to/haproxy.cfg:/bitnami/haproxy/conf/haproxy.cfg

Check the official HAProxy documentation to understand the possible configurations.

Using docker-compose.yaml

Please be aware this file has not undergone internal testing. Consequently, we advise its use exclusively for development or testing purposes. For production-ready deployments, we highly recommend utilizing its associated Bitnami Helm chart.

If you detect any issue in the docker-compose.yaml file, feel free to report it or contribute with a fix by following our Contributing Guidelines.

Contributing

We'd love for you to contribute to this container. You can request new features by creating an issue or submitting a pull request with your contribution.

Issues

If you encountered a problem running this container, you can file an issue. For us to provide better support, be sure to fill the issue template.

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Instalação HAPROXY docker

How to Run HAProxy With Docker (In-Depth Guide)

Link: https://www.haproxy.com/blog/how-to-run-haproxy-with-docker

8 min read

Nick Ramirez

Can you run HAProxy as a Docker container? Yes! Did you even need to ask? Docker is ubiquitous these days and you’ll find that many applications have been Docker-ized; the HAProxy load balancer is no exception. Pardon the cliché, but HAProxy was born for this. As a standalone service that runs on Linux, porting it to Docker certainly seemed natural.

Need advanced, enterprise-grade features?

HAProxy Enterprise is a flexible data plane layer that provides high-performance load balancing for TCP, UDP, QUIC, and HTTP-based applications, high availability, an API/AI gateway, Kubernetes application routing, SSL processing, DDoS protection, bot management, global rate limiting, and a next-generation WAF. 

HAProxy Enterprise is a core component of HAProxy One: the world's fastest application delivery and security platform that is the G2 category leader in API management, container networking, DDoS protection, web application firewall (WAF), and load balancing.

Why would you want to run your load balancer inside of a Docker container? Are their performance penalties when doing so? Will it introduce any security issues?

In this blog post, you’ll learn why you might consider running HAProxy inside a container and what the ramifications could be. Then you’ll see how to do it. Note that if you want to use HAProxy for Kubernetes traffic management, we encourage you to view our Kubernetes solution to see what’s possible.

HAProxy Technologies builds its own set of Docker images under its namespace haproxytech. These are updated regularly with the latest patches and security updates. I will be using those images in this blog post. You’ll find them here:

The commands I demonstrate were performed on a Linux workstation but will work just as well when using Docker Desktop for Windows or Docker Desktop for Mac.

​#The Benefits of Docker

Do you want the ability to run HAProxy without needing to compile it, install dependencies, or otherwise alter your system?

Docker containers bring considerable benefits, chief among them being less ceremony around installation and execution. Docker allows you to drop a container onto a host system and instantly get a running service—no install scripts, no installing C libraries. The service is completely contained within the container and all you need to do is start it and then map a TCP port to it. When you deploy a container, you gain the ability to run an entire application complete with its runtime environment without ever actually installing it onto the host system.

Lifecycle management becomes standardized too. Starting, stopping, and removing a container is as easy as calling one-line docker commands. That in turn makes deployment a repeatable and testable process. It also lends itself to easier software upgrades.

​#The Performance Impact of Running Docker

You want your load balancer to be fast, with no added latency from the environment. So, the question is, what is the impact of running HAProxy inside of a container?

In terms of CPU overhead, it helps to remember that, unlike a virtual machine, Docker does not require a layer of virtualization on top of the host operating system. A container runs on the host’s kernel and is basically just another process, albeit one with better isolation from other processes running on the host (it uses namespaces to accomplish this). It should come as little surprise then that a study by researchers at IBM found that the CPU overhead of using Docker is negligible.

Networking is another story. By default, Docker lets you access the services running inside containers by creating a bridge network to the host. This does incur latency due to the network address translation (NAT) that must happen between the container’s local network and the host’s bridge network. In the same IBM study cited before, the researchers found that Docker’s NAT doubled latency from roughly 35 µs to 70 µs for a 100-byte request from the client and a 200-byte response from the application.

On the other hand, bridge networks are useful because they allow you to isolate groups of containers into a container-only network and expose only some of those containers to the host, which is handy for reducing the number of IP addresses required on your host’s network (think about the number of IPs required to run hundreds or possibly thousands of containers).

If you require very low latency you can switch to using Docker’s host network feature, which allows your container to share the same network as the host, cutting out the need for NAT. Then again, that doesn’t touch on what to do if you want to run Docker Swarm or Kubernetes, which use overlay networks, for which different network drivers like Project Calico and Cilium have solutions. However, that is outside the scope of this article.

In short, unless you require very low latency, you should be fine sticking with the default bridge networking option. Just be sure to test it out and see if you’re getting the throughput you need.

​#Security Considerations of Running Docker

You may be concerned by the fact that many Docker containers run their service as root, and this root user is the same root user as on the host system. Concerns about a container breakout are legitimate. HAProxy runs as root too. However, to put your mind at ease: HAProxy requires root access because it needs to bind to restricted TCP ports like 80 and 443. However, once it has finished its startup, it drops its root privileges and runs as an unprivileged user.

People also weigh the risk that a container may be malicious. This is a good reason to stick with the haproxytech Docker images, which are curated by HAProxy Technologies.

​#Run Haproxy With Docker

We’ll create three instances of a web application, one instance of HAProxy, and a bridge network to join them together. So, once you’ve installed Docker, use the following command to create a new bridge network in Docker:

$ sudo docker network create --driver=bridge mynetwork

Then use the docker run command to create and run three instances of the web application. In this example, I use the Docker image jmalloc/echo-server. It’s a simple web app that returns back the details of the HTTP requests that you send to it.

$ sudo docker run -d \
--name web1 --net mynetwork jmalloc/echo-server:latest
$ sudo docker run -d \
--name web2 --net mynetwork jmalloc/echo-server:latest
$ sudo docker run -d \
--name web3 --net mynetwork jmalloc/echo-server:latest

Notice that we assign each one a unique name and attach it to the bridge network we created. You should now have three web applications running, which you can verify by calling the docker ps command:

$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
98216bb8c5ff jmalloc/echo-server:latest "/bin/echo-server" About a minute ago Up About a minute 8080/tcp web3
ae6accc111d9 jmalloc/echo-server:latest "/bin/echo-server" About a minute ago Up About a minute 8080/tcp web2
554fafbc2b3b jmalloc/echo-server:latest "/bin/echo-server" About a minute ago Up About a minute 8080/tcp web1

These containers listen on their own port 8080, but we did not map those ports to the host, so they are not routable. We’ll relay traffic to these containers via the HAProxy load balancer. Next, let’s add HAProxy in front of them. Create a file named haproxy.cfg in the current directory and add the following to it:

global
stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
log stdout format raw local0 info
defaults
mode http
timeout client 10s
timeout connect 5s
timeout server 10s
timeout http-request 10s
log global
frontend stats
bind *:8404
stats enable
stats uri /
stats refresh 10s
frontend myfrontend
bind :80
default_backend webservers
backend webservers
server s1 web1:8080 check
server s2 web2:8080 check
server s3 web3:8080 check

A few things to note:

  • In the global section, the stats socket line enables the HAProxy Runtime API and also enables seamless reloads of HAProxy.

  • The first frontend listens on port 8404 and enables the HAProxy Stats dashboard, which displays live statistics about your load balancer.

  • The other frontend listens on port 80 and dispatches requests to one of the three web applications listed in the webservers backend.

  • Instead of using the IP address of each web app, we’re using their hostnames web1web2, and web3. You can use this type of DNS-based routing when you create a Docker bridge network as we’ve done.

Next, create and run an HAProxy container and map its port 80 to the same port on the host by including the -p argument. Also, map port 8404 for the HAProxy Stats page:

$ sudo docker run -d \
--name haproxy \
--net mynetwork \
-v $(pwd):/usr/local/etc/haproxy:ro \
-p 80:80 \
-p 8404:8404 \
haproxytech/haproxy-alpine:2.4

Calling docker ps afterwards shows that HAProxy is running:

$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d734d0ef2635 haproxytech/haproxy-alpine:2.4 "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:8404->8404/tcp haproxy

You can access the echo-server web application at http://localhost. Each request to it will be load balanced by HAProxy. Also, you can see the HAProxy Stats page at http://localhost:8404.

If you make a change to your haproxy.cfg file, you can reload the load balancer—without disrupting traffic—by calling the docker kill command:

$ sudo docker kill -s HUP haproxy

To delete the containers and network, run the docker stopdocker rm, and docker network rm commands:

$ sudo docker stop web1 && sudo docker rm web1
$ sudo docker stop web2 && sudo docker rm web2
$ sudo docker stop web3 && sudo docker rm web3
$ sudo docker stop haproxy && sudo docker rm haproxy
$ sudo docker network rm mynetwork

​#Conclusion

In this blog post, you learned how running HAProxy inside of a Docker container can simplify its deployment and lifecycle management. Docker provides a standardized way for deploying applications, making the process repeatable and testable. While the CPU overhead of running Docker is negligible, it can incur extra network latency, but the impact of that depends on your use case and throughput needs.

To run HAProxy, simply create an HAProxy configuration file and then call the docker run command with the name of the HAProxy Docker image. HAProxy Technologies supplies up-to-date Docker images on Docker Hub.

Want to know when more content like this is published? Subscribe to our blog or follow us on Twitter. You can also join the conversation on Slack.


Get the latest release updates, tutorials, and deep-dives from HAProxy experts.

Authors Nick Ramirez

Nick creates technical content for HAProxy Technologies ranging from documentation and blog posts to Wikipedia articles, GitHub READMEs and Stack Overflow answers. With a background in web development and DevOps, he has fun digging into product features and discovering the optimal path for a new blog tutorial.