{"id":6349,"date":"2018-03-16T06:14:18","date_gmt":"2018-03-16T06:14:18","guid":{"rendered":"https:\/\/blog.cloudthat.com\/?p=6349"},"modified":"2024-06-25T11:11:23","modified_gmt":"2024-06-25T11:11:23","slug":"how-to-make-your-app-containers-highly-available-with-haproxy","status":"publish","type":"blog","link":"https:\/\/www.cloudthat.com\/resources\/blog\/how-to-make-your-app-containers-highly-available-with-haproxy","title":{"rendered":"How to make your App Containers Highly Available with HAProxy?"},"content":{"rendered":"<p>In this article, we will discuss how to host multiple applications in Docker containers and make them highly available. I will try to keep this discussion as simple as possible.<\/p>\n<p>Let\u2019s start from scratch and for that, I will break this article in two parts:<\/p>\n<ol>\n<li>How to route traffic to multiple applications in Docker?<\/li>\n<li>How to make the containers more available?<\/li>\n<\/ol>\n<p>Before I start, I am assuming that you have basic knowledge of Docker.<\/p>\n<p>Hosting multiple applications in Docker is generally achieved by hosting them in different containers. Now the question is <strong>How do you think we can configure all the applications to accept traffic on port 80?<\/strong><\/p>\n<p>Ideally, we cannot make all our containers listen on the same public port 80, instead we must make them listen on some random ports like 8081,4035, etc. But, when someone visits a site, traffic is routed to port 80, so somehow, we need to accept the requests on port 80 and forward them to corresponding container to serve them.<\/p>\n<p>There are several ways to do this, we can configure Nginx in a container and make it act as a reverse proxy. But, I don\u2019t prefer to use a webserver to solve this problem. Here, we will use HAProxy which is a reverse proxy server, capable of doing load balancing as well, which is an added advantage.<\/p>\n<p>To perform the tasks, we will start one container with HAProxy and two containers with two demo sites.<\/p>\n<h2><strong>How to route traffic to multiple applications in Docker?<\/strong><\/h2>\n<p>Here, I have deployed three containers, one for HAProxy and other two containers for two demo sites. For demo sites, I have configured Apache in Ubuntu containers to show dummy pages.<\/p>\n<p><a href=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/HAProxy_image1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6351\" src=\"https:\/\/content.cloudthat.com\/resources\/wp-content\/uploads\/2022\/11\/HAProxy_image1.png\" alt=\"\" width=\"1026\" height=\"104\" \/><\/a><\/p>\n<p>To start the HAProxy container, please use the following commands and start the service.<\/p>\n<pre class=\"lang:default decode:true\">$ Docker run -d \u2013name haproxy -p 80:80 ubuntu:latest\r\n$ Docker exec -it haproxy \/bin\/bash\r\nContainer# apt-get update -y\r\nContainer# apt-get install haproxy\r\nContainer# service haproxy start\r\n<\/pre>\n<p>We have HAProxy configured on port 80 and any traffic comes to this host server will hit HAProxy. Now, we must route traffic to specific containers based on the request, and for that we must do some configuration in the HAProxy config file.<\/p>\n<p>Edit HAProxy configuration file:<\/p>\n<pre class=\"lang:default decode:true\">nano \/etc\/haproxy\/haproxy.cfg<\/pre>\n<pre class=\"lang:default decode:true\">frontend http-in\r\n    bind *:80\r\n    acl is_site1 hdr_end(host) -i site1.container.com\r\n    acl is_site2 hdr_end(host) -i site2.container.com\r\n\r\n    use_backend site1 if is_site1\r\n    use_backend site2 if is_site2\r\n\r\nbackend site1\r\n    server s1 site1.container.com\r\n\r\nbackend site2\r\n    server s2 site2.container.com\r\n<\/pre>\n<p>Please add the above block in the HAProxy configuration file and change the \u2018mode\u2019 property in default block to \u2018mode http\u2019 to accept http requests. And finally restart the service.<\/p>\n<pre class=\"lang:default decode:true\">$ service haproxy restart<\/pre>\n<p>In \u2018frontend http-in\u2019, we specified our sites and configured how HAProxy will select a backend server to forward the request. In next two blocks, we have defined backend servers for the two demo sites.<\/p>\n<p>The backend servers that we have specified here (site1.container.com and site2.container.com) are just two dummy names for the containers hosting the dummy sites.<\/p>\n<p>To send traffic to those containers we need to assign IPs to these dummy sites. Let\u2019s make those entries in \/etc\/hosts file.<\/p>\n<pre class=\"lang:default decode:true\">172.0.1.1\tsite1.container.com\r\n172.0.1.2\tsite2.container.com\r\n<\/pre>\n<p>And it\u2019s done! Now pass site1.container.com or site2.container.com as header with the host server IP and you can see that HAProxy is routing traffic to specific containers based on the request.<\/p>\n<p>At this point, one question that you might have, \u201cWhy have I used dummy site names in backend servers and then make the entries in \/etc\/hosts file? I could have used the container IPs directly as the backend server. What is the problem in that?\u201d<\/p>\n<p>Of-course, we can use the container IPs directly as backend servers and make the whole process run smoothly. But, what if a container exits and come up with a new IP due to some internal errors? Do you think HAProxy can route traffic to those new containers?<\/p>\n<p>In both the cases, either you have done entries in \/etc\/hosts file or you have entries in haproxy.cfg file, you must change those IPs manually every time, whenever a container exits and come up with a new IP.<\/p>\n<p>Instead of doing it manually every time, can\u2019t we automate it? And let the automation script take care of the changes in the configuration.<\/p>\n<p>In the next part, we will automate this process to eliminate the manual tasks and discuss how to make applications running in Docker environment, highly available.<\/p>\n<p>Please feel free to post your views in the comment section below, I will be more than happy to discuss.<\/p>\n<p>Stay tuned to know more about the new features and services in my further articles.<\/p>\n<p>To know more about our training services, visit\u00a0<a href=\"http:\/\/www.cloudthat.in\/?utm_source=blog-website&amp;utm-medium=text-link&amp;utm_campaign=how-to-make-your-app-containers-highly-available-with-haproxy\" target=\"_blank\" rel=\"noopener\">www.cloudthat.in<\/a>\u00a0and for consulting services, visit\u00a0<a href=\"http:\/\/www.cloudthat.com\/?utm_source=blog-website&amp;utm-medium=text-link&amp;utm_campaign=how-to-make-your-app-containers-highly-available-with-haproxy\" target=\"_blank\" rel=\"noopener\">www.cloudthat.com<\/a><\/p>\n","protected":false},"author":219,"featured_media":6355,"parent":0,"comment_status":"open","ping_status":"open","template":"","blog_category":[3607,3892],"user_email":"prarthitm@cloudthat.com","published_by":"324","primary-authors":"","secondary-authors":"","acf":[],"_links":{"self":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog\/6349"}],"collection":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/users\/219"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/comments?post=6349"}],"version-history":[{"count":1,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog\/6349\/revisions"}],"predecessor-version":[{"id":46126,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog\/6349\/revisions\/46126"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/media?parent=6349"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.cloudthat.com\/resources\/wp-json\/wp\/v2\/blog_category?post=6349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}