Deploy HAProxy as a Docker Container

Follow through this tutorial to learn how to deploy HAProxy as a Docker container. HAProxyis a free, very fast and reliable reverse-proxy offering high availability, load balancing, and proxying for TCP and HTTP-based applications“.

Deploy HAProxy as a Docker Container

HAProxy can be run by installing it as a package using your specific Linux distribution package manager or by deploying it as a Docker container.

Install Docker on Linux

Check our previous tutorials on how to install Docker on Linux.

Download HAProxy Official Docker Image

Once the Docker is installed, you can then pull the official latest HAProxy Docker image from Docker Hub;

docker pull haproxy

You can list available images using the command below;

docker images

Create Your HAProxy Configuration

Depending on your needs, create your HAProxy configuration before hand on your host system. We will configure the HAProxy Docker container to use this configuration.

In our setup, we have placed the configuration under the /opt/haproxy directory as haproxy.cfg.

This is how our sample configuration file looks like;

cat /opt/haproxy/haproxy.cfg
global
    log         stdout format raw local0
    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    

frontend main
    bind 	*:80 
    default_backend web01
    http-request capture req.hdr(Host) len 64
    http-request capture req.hdr(Referer) len 64
    http-request capture req.hdr(Content-Lenght) len 64
    http-request capture req.hdr(User-Agent) len 64

backend web01
    server  backend01   192.168.57.47:80 check

listen stats
    bind  *:8888   
    stats enable                      
    stats hide-version              
    stats refresh 30s               
    stats show-node                 
    stats auth rproxy:P@ssw0rd     
    stats uri /stats

For HAProxy configured with SSL/TLS for both the frontend and backend, as well as the HAProxy stats page SSL/TLS;


global
    log         stdout format raw local0
    stats socket /var/lib/haproxy/stats
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    

frontend main
    bind	*:80
    bind 	*:443 ssl  crt  /usr/local/etc/haproxy/cert.pem
    http-request redirect scheme https code 301 if !{ ssl_fc }
    default_backend web01
    http-request capture req.hdr(Host) len 64
    http-request capture req.hdr(Referer) len 64
    http-request capture req.hdr(Content-Lenght) len 64
    http-request capture req.hdr(User-Agent) len 64

backend web01
    server  backend01   backend.kifarunix-demo.com:443 check ssl verify none

listen stats
    bind  *:8888 ssl  crt  /usr/local/etc/haproxy/cert.pem
    stats enable                      
    stats hide-version              
    stats refresh 30s               
    stats show-node                 
    stats auth rproxy:P@ssw0rd     
    stats uri /stats

Check HAProxy Configuration Syntax

Once you have the configuration file ready, you need to test it for validity. This can be done by running the command below;

docker run -it --rm -v /opt/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg \
--name haconfig-syntax-check haproxy haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg

The command above basically creates a docker container haconfig-syntax-check using the haproxy image downloaded above, mounts our /opt/haproxy/haproxy.cfg config on the container /usr/local/etc/haproxy/haproxy.cfg, and run the test using the command haproxy haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg.

If all is good, you should get such an output as Configuration file is valid.

Otherwise, errors will be printed to standard output.

For the config with SSL/TLS enabled;

docker run -it --rm -v /opt/haproxy/:/usr/local/etc/haproxy/ \
--name haconfig-syntax-check haproxy haproxy \
-c -f /usr/local/etc/haproxy/haproxy.cfg

In this example, the certificate files and haproxy.cfg file is placed on the host directory, /opt/haproxy/ which mounted on /usr/local/etc/haproxy/ on the HAProxy docker container.

Create HAProxy Docker Network

To isolate containers into their own container-only networks, you need to create a Docker network.

Run the command below to create Docker network. You can name your network as you wish.

docker network create haproxynet

By default, a bridged network is created.

You can list available Docker networks;

docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
a86e1291a1b1   bridge         bridge    local
752b45df0a54   haproxynet     bridge    local
623092a3cbbc   host           host      local
71a9309810ee   none           null      local
82b49e609d04   root_default   bridge    local

Deploy HAProxy Docker Container

You are now ready to deploy HAProxy Docker container.

docker run -d --network haproxynet --name haproxy \
-v /opt/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg \
-p 80:80 -p 8888:8888 haproxy

The command creates a Docker container named haproxy using the haproxy image, mounts our configuration /opt/haproxy/haproxy.cfg in the Docker container as /usr/local/etc/haproxy/haproxy.cfg and run it in the background, -d. It then exposes the HAProxy container port 80 on hosts port 80 (-p 80:80) and -p 8888:8888 for stats.

docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                                                          NAMES
93ea8acc4644   haproxy   "docker-entrypoint.s…"   8 seconds ago   Up 7 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:8888->8888/tcp, :::8888->8888/tcp   haproxy

Open Port 80/443/8888 on Firewall to allow external access.

If you are using HAProxy with SSL enabled;

docker run -d --network haproxynet --name haproxy \
-v /opt/haproxy/:/usr/local/etc/haproxy/ -p 80:80 \
-p 443:443 -p 8888:8888 haproxy

You can now access your web server using the address http://haproxy-ip-or-hostname.

You can access the HAProxy stats using the address http[s]://haproxy-ip-or-hostname:8888 and use the credentials set.

deploy HAProxy as a Docker container

You can also view the Docker container logs manually;

docker logs --tail -20 haproxy

...
192.168.56.1:56614 [29/Jul/2022:20:09:41.366] stats stats/ 0/0/0/0/0 200 21282 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:56646 [29/Jul/2022:20:10:11.508] stats stats/ 0/0/0/0/0 200 21282 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:56678 [29/Jul/2022:20:10:41.663] stats stats/ 0/0/0/0/0 200 21282 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:56722 [29/Jul/2022:20:11:11.783] stats stats/ 0/0/0/0/0 200 21286 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:56754 [29/Jul/2022:20:11:41.856] stats stats/ 0/0/0/0/0 200 21287 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:56786 [29/Jul/2022:20:12:11.905] stats stats/ 0/0/0/0/0 200 21287 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:56820 [29/Jul/2022:20:12:41.998] stats stats/ 0/0/0/0/0 200 21291 - - LR-- 1/1/0/0/0 0/0 "GET /stats HTTP/1.1"
192.168.56.1:53768 [29/Jul/2022:20:13:02.841] main web01/backend01 0/0/1/0/1 404 436 - - ---- 1/1/0/0/0 0/0 {192.168.56.124|||like Gecko) Chrome/104.0.0.0 Safari/537.36} "GET /index.php HTTP/1.1"
192.168.56.1:53768 [29/Jul/2022:20:13:09.760] main web01/backend01 0/0/2/1/3 200 3400 - - ---- 1/1/0/0/0 0/0 {192.168.56.124|||like Gecko) Chrome/104.0.0.0 Safari/537.36} "GET / HTTP/1.1"
192.168.56.1:53830 [29/Jul/2022:20:13:54.521] main web01/backend01 0/0/1/1/3 200 3400 - - ---- 1/1/0/0/0 0/0 {192.168.56.124|||like Gecko) Chrome/104.0.0.0 Safari/537.36} "GET /?doc=ls%20bin/bash HTTP/1.1"

You can also view the logs automatically using Dozzle.

Install Dozzle Real-Time Log Viewer for Docker Containers

And that is how you can run HAProxy as a Docker container.

Other Tutorials

Install Guacamole as Docker Container on Rocky Linux

Install ModSecurity 3 with Apache in a Docker Container

SUPPORT US VIA A VIRTUAL CUP OF COFFEE

We're passionate about sharing our knowledge and experiences with you through our blog. If you appreciate our efforts, consider buying us a virtual coffee. Your support keeps us motivated and enables us to continually improve, ensuring that we can provide you with the best content possible. Thank you for being a coffee-fueled champion of our work!

Photo of author
gen_too
Co-founder of Kifarunix.com, Linux Tips and Tutorials. Linux/Unix admin and author at Kifarunix.com.

Leave a Comment