{"id":13797,"date":"2022-07-30T22:35:49","date_gmt":"2022-07-30T19:35:49","guid":{"rendered":"https:\/\/kifarunix.com\/?p=13797"},"modified":"2024-03-09T16:14:29","modified_gmt":"2024-03-09T13:14:29","slug":"deploy-haproxy-as-a-docker-container","status":"publish","type":"post","link":"https:\/\/kifarunix.com\/deploy-haproxy-as-a-docker-container\/","title":{"rendered":"Deploy HAProxy as a Docker Container"},"content":{"rendered":"\n<p>Follow through this tutorial to learn how to deploy HAProxy as a Docker container. <a href=\"https:\/\/www.haproxy.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">HAProxy<\/a> &#8220;<em>is a free, very fast and reliable reverse-proxy offering\u00a0high availability,\u00a0load balancing, and proxying for TCP and HTTP-based applications<\/em>&#8220;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Deploy HAProxy as a Docker Container<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install Docker on Linux<\/h3>\n\n\n\n<p>Check our previous tutorials on <a href=\"https:\/\/kifarunix.com\/?s=install+docker\" target=\"_blank\" rel=\"noreferrer noopener\">how to install Docker on Linux<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Download HAProxy Official Docker Image<\/h3>\n\n\n\n<p>Once the Docker is installed, you can then pull the official latest HAProxy Docker image from Docker Hub;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker pull haproxy<\/code><\/pre>\n\n\n\n<p>You can list available images using the command below;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker images<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Create Your HAProxy Configuration<\/h3>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>In our setup, we have placed the configuration under the <code>\/opt\/haproxy<\/code> directory as <code>haproxy.cfg<\/code>.<\/p>\n\n\n\n<p>This is how our sample configuration file looks like;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/opt\/haproxy\/haproxy.cfg<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>global\n    log         stdout format raw local0\n    stats socket \/var\/lib\/haproxy\/stats\n\ndefaults\n    mode                    http\n    log                     global\n    option                  httplog\n    option                  dontlognull\n    option http-server-close\n    option forwardfor       except 127.0.0.0\/8\n    option                  redispatch\n    retries                 3\n    timeout http-request    10s\n    timeout queue           1m\n    timeout connect         10s\n    timeout client          1m\n    timeout server          1m\n    timeout http-keep-alive 10s\n    timeout check           10s\n    maxconn                 3000\n    \n\nfrontend main\n    bind \t*:80 \n    default_backend web01\n    http-request capture req.hdr(Host) len 64\n    http-request capture req.hdr(Referer) len 64\n    http-request capture req.hdr(Content-Lenght) len 64\n    http-request capture req.hdr(User-Agent) len 64\n\nbackend web01\n    server  backend01   192.168.57.47:80 check\n\nlisten stats\n    bind  *:8888   \n    stats enable                      \n    stats hide-version              \n    stats refresh 30s               \n    stats show-node                 \n    stats auth rproxy:P@ssw0rd     \n    stats uri \/stats\n<\/code><\/pre>\n\n\n\n<p>For HAProxy configured with SSL\/TLS for both the frontend and backend, as well as the HAProxy stats page SSL\/TLS;<\/p>\n\n\n\n<pre class=\"scroll-box\"><code>\nglobal\n    log         stdout format raw local0\n    stats socket \/var\/lib\/haproxy\/stats\n    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\n    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256\n    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets\n\ndefaults\n    mode                    http\n    log                     global\n    option                  httplog\n    option                  dontlognull\n    option http-server-close\n    option forwardfor       except 127.0.0.0\/8\n    option                  redispatch\n    retries                 3\n    timeout http-request    10s\n    timeout queue           1m\n    timeout connect         10s\n    timeout client          1m\n    timeout server          1m\n    timeout http-keep-alive 10s\n    timeout check           10s\n    maxconn                 3000\n    \n\nfrontend main\n    bind\t*:80\n    bind \t*:443 ssl  crt  \/usr\/local\/etc\/haproxy\/cert.pem\n    http-request redirect scheme https code 301 if !{ ssl_fc }\n    default_backend web01\n    http-request capture req.hdr(Host) len 64\n    http-request capture req.hdr(Referer) len 64\n    http-request capture req.hdr(Content-Lenght) len 64\n    http-request capture req.hdr(User-Agent) len 64\n\nbackend web01\n    server  backend01   backend.kifarunix-demo.com:443 check ssl verify none\n\nlisten stats\n    bind  *:8888 ssl  crt  \/usr\/local\/etc\/haproxy\/cert.pem\n    stats enable                      \n    stats hide-version              \n    stats refresh 30s               \n    stats show-node                 \n    stats auth rproxy:P@ssw0rd     \n    stats uri \/stats\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Check HAProxy Configuration Syntax<\/h3>\n\n\n\n<p>Once you have the configuration file ready, you need to test it for validity. This can be done by running the command below;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -it --rm -v \/opt\/haproxy\/haproxy.cfg:\/usr\/local\/etc\/haproxy\/haproxy.cfg \\\n--name haconfig-syntax-check haproxy haproxy -c -f \/usr\/local\/etc\/haproxy\/haproxy.cfg<\/code><\/pre>\n\n\n\n<p>The command above basically creates a docker container <strong>haconfig-syntax-check<\/strong> using the <strong>haproxy<\/strong> image downloaded above, mounts our <code>\/opt\/haproxy\/haproxy.cfg<\/code> config on the container <code>\/usr\/local\/etc\/haproxy\/haproxy.cfg<\/code>, and run the test using the command <strong><code>haproxy haproxy -c -f \/usr\/local\/etc\/haproxy\/haproxy.cfg<\/code><\/strong>.<\/p>\n\n\n\n<p>If all is good, you should get such an output as <code><strong>Configuration file is valid<\/strong><\/code>.<\/p>\n\n\n\n<p>Otherwise, errors will be printed to standard output.<\/p>\n\n\n\n<p>For the config with SSL\/TLS enabled;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -it --rm -v \/opt\/haproxy\/:\/usr\/local\/etc\/haproxy\/ \\\n--name haconfig-syntax-check haproxy haproxy \\\n-c -f \/usr\/local\/etc\/haproxy\/haproxy.cfg<\/code><\/pre>\n\n\n\n<p>In this example, the certificate files and haproxy.cfg file is placed on the host directory, <strong><code>\/opt\/haproxy\/<\/code><\/strong> which mounted on <strong><code>\/usr\/local\/etc\/haproxy\/<\/code><\/strong> on the HAProxy docker container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create HAProxy Docker Network<\/h3>\n\n\n\n<p>To isolate containers into their own container-only networks, you need to create a <a href=\"https:\/\/docs.docker.com\/network\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker network<\/a>.<\/p>\n\n\n\n<p>Run the command below to create Docker network. You can name your network as you wish.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker network create haproxynet<\/code><\/pre>\n\n\n\n<p>By default, a bridged network is created.<\/p>\n\n\n\n<p>You can list available Docker networks;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker network ls<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>NETWORK ID     NAME           DRIVER    SCOPE\na86e1291a1b1   bridge         bridge    local\n<strong>752b45df0a54   haproxynet     bridge    local\n<\/strong>623092a3cbbc   host           host      local\n71a9309810ee   none           null      local\n82b49e609d04   root_default   bridge    local<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Deploy HAProxy Docker Container<\/h3>\n\n\n\n<p>You are now ready to deploy HAProxy Docker container.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -d --network haproxynet --name haproxy \\\n-v \/opt\/haproxy\/haproxy.cfg:\/usr\/local\/etc\/haproxy\/haproxy.cfg \\\n-p 80:80 -p 8888:8888 haproxy<\/code><\/pre>\n\n\n\n<p>The command creates a Docker container named <strong>haproxy<\/strong> using the <strong>haproxy<\/strong> image, mounts our configuration <code><strong>\/opt\/haproxy\/haproxy.cfg<\/strong><\/code> in the Docker container as <code>\/usr\/local\/etc\/haproxy\/haproxy.cfg<\/code> and run it in the background, <strong><code>-d<\/code><\/strong>. It then exposes the HAProxy container port 80 on hosts port 80 (<strong><code>-p 80:80<\/code><\/strong>) and <code><strong>-p 8888:8888<\/strong><\/code> for stats.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker ps<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                                                          NAMES\n93ea8acc4644   haproxy   \"docker-entrypoint.s\u2026\"   8 seconds ago   Up 7 seconds   0.0.0.0:80-&gt;80\/tcp, :::80-&gt;80\/tcp, 0.0.0.0:8888-&gt;8888\/tcp, :::8888-&gt;8888\/tcp   haproxy<\/code><\/pre>\n\n\n\n<p>Open Port 80\/443\/8888 on Firewall to allow external access.<\/p>\n\n\n\n<p>If you are using HAProxy with SSL enabled;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -d --network haproxynet --name haproxy \\\n-v \/opt\/haproxy\/:\/usr\/local\/etc\/haproxy\/ -p 80:80 \\\n-p 443:443 -p 8888:8888 haproxy<\/code><\/pre>\n\n\n\n<p>You can now access your web server using the address <strong>http:\/\/haproxy-ip-or-hostname<\/strong>.<\/p>\n\n\n\n<p>You can access the HAProxy stats using the address <strong>http[s]:\/\/haproxy-ip-or-hostname:8888<\/strong> and use the credentials set.<\/p>\n\n\n\n<div><a href=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2022\/08\/haproxy-docker-container-stats.png\" class=\"td-modal-image\"><figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1893\" height=\"610\" src=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2022\/08\/haproxy-docker-container-stats.png\" alt=\"deploy HAProxy as a Docker container\" class=\"wp-image-13828\" title=\"\" srcset=\"https:\/\/kifarunix.com\/wp-content\/uploads\/2022\/08\/haproxy-docker-container-stats.png?v=1661886925 1893w, https:\/\/kifarunix.com\/wp-content\/uploads\/2022\/08\/haproxy-docker-container-stats-768x247.png?v=1661886925 768w, https:\/\/kifarunix.com\/wp-content\/uploads\/2022\/08\/haproxy-docker-container-stats-1536x495.png?v=1661886925 1536w\" sizes=\"(max-width: 1893px) 100vw, 1893px\" \/><\/figure><\/a><\/div>\n\n\n\n<p>You can also view the Docker container logs manually;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker logs --tail -20 haproxy<\/code><\/pre>\n\n\n\n<pre class=\"scroll-box\"><code>\n...\n192.168.56.1:56614 [29\/Jul\/2022:20:09:41.366] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21282 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.168.56.1:56646 [29\/Jul\/2022:20:10:11.508] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21282 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.168.56.1:56678 [29\/Jul\/2022:20:10:41.663] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21282 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.168.56.1:56722 [29\/Jul\/2022:20:11:11.783] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21286 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.168.56.1:56754 [29\/Jul\/2022:20:11:41.856] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21287 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.168.56.1:56786 [29\/Jul\/2022:20:12:11.905] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21287 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.168.56.1:56820 [29\/Jul\/2022:20:12:41.998] stats stats\/<STATS> 0\/0\/0\/0\/0 200 21291 - - LR-- 1\/1\/0\/0\/0 0\/0 \"GET \/stats HTTP\/1.1\"\n192.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\"\n192.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\"\n192.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\"\n<\/code><\/pre>\n\n\n\n<p>You can also view the logs automatically using Dozzle.<\/p>\n\n\n\n<p><a href=\"https:\/\/kifarunix.com\/install-dozzle-real-time-log-viewer-for-docker-containers-on-ubuntu\/\" target=\"_blank\" rel=\"noreferrer noopener\">Install Dozzle&nbsp;Real-Time Log Viewer for&nbsp;Docker Containers<\/a><\/p>\n\n\n\n<p>And that is how you can run HAProxy as a Docker container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Other Tutorials<\/h3>\n\n\n\n<p><a href=\"https:\/\/kifarunix.com\/install-guacamole-as-docker-container-on-rocky-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">Install Guacamole as Docker Container on Rocky Linux<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/kifarunix.com\/install-modsecurity-3-with-apache-in-a-docker-container\/\" target=\"_blank\" rel=\"noreferrer noopener\">Install ModSecurity 3 with Apache in a Docker Container<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Follow through this tutorial to learn how to deploy HAProxy as a Docker container. HAProxy &#8220;is a free, very fast and reliable reverse-proxy offering\u00a0high availability,\u00a0load<\/p>\n","protected":false},"author":3,"featured_media":13832,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_lock_modified_date":false,"footnotes":""},"categories":[121,1076,1077,1032,92,36],"tags":[5726,5728,1033,5727,5729],"class_list":["post-13797","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-howtos","category-containers","category-docker","category-haproxy","category-load-balancers","category-virtualization","tag-deploy-haproxy-as-docker","tag-docker-container-haproxy","tag-haproxy","tag-haproxy-docker-container","tag-haproxy-ssl-docker-container","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50","resize-featured-image"],"_links":{"self":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/13797"}],"collection":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/comments?post=13797"}],"version-history":[{"count":8,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/13797\/revisions"}],"predecessor-version":[{"id":20581,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/posts\/13797\/revisions\/20581"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/media\/13832"}],"wp:attachment":[{"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/media?parent=13797"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/categories?post=13797"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kifarunix.com\/wp-json\/wp\/v2\/tags?post=13797"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}