Categories
Automation DevOps

HaProxy as HTTP proxy using Docker

While HaProxy has many uses, I’ll show how HaProxy can act as HTTP proxy. Why might you need it? For example, in order to forward HTTP traffic between 2 unreachable networks. As always, Docker will help us to raise a fully functional demo. Keep reading to find out how 🙂

Prerequisites

Install on your machine:

  • docker
  • docker-compose
  • git

The tutorial assumes familiarity with:

  • basic HaProxy functionality.
  • basic git, docker and docker-compose commands.

Demo Architecture

In short, we’ll have 2 networks A and B. Network A includes HTTP client which wants to access HTTP server in Network B. Sadly, 2 networks are unreachable. However, there’s a green host which belongs to both networks. What can we do to connect both networks? There could be many solutions, of course. I’ve chosen HTTP proxy one. To demonstrate the idea, we’ll use HaProxy. Specifically, it will forward requests from HTTP client in network A to HTTP server in network B.

To illustrate the architecture, see simple diagram below:

HaProxy as HTTP proxy

HaProxy as HTTP proxy demo

As always, clone sample project from my github. Compose file describes our architecture.

There I defined 3 services: http_client, http_server, c. Below, we’ll describe each in short.

HTTP Client

Our HTTP client is a basic Python HTTP client based on requests library. We would like to test that HaProxy forwards requests to http_server . To this end, let’s send single request to our proxy using http://http_proxy URL.

import requests

if __name__ == '__main__':
    r = requests.get('http://http_proxy')
    print(r.text)

HTTP Server

Next, we have http_server. To simplify things, I selected HashiCorp HTTP echo server which is based on hashicorp/http-echo docker image. As the name suggests, it returns the text it was started with. Naturally, I’ve started it with hello world text, as you can see in http_server command . Note that HTTP server listens at port 5678.

HaProxy as HTTP proxy

Lastly, we have HaProxy named as http_proxy in Compose file. You can find HTTP proxy configuration in haproxy.cfg mapped to http_proxy service using Docker Volumes.

The most interesting configuration is below:

frontend myfrontend
  bind :80
  default_backend demo_server

backend demo_server
  http-request set-header Host http_server
  server demo_server http_server:5678 check

As you can see, HaProxy just forwards all HTTP requests it receives on port 80 to http_server at port 5678. Note that HaProxy connects to HTTP server by service name.

Demo time

Let’s raise our demo stack using docker-compose -p demo up http_client command. As expected, our HTTP client gets hello world text in the response.

Creating network "demo_default" with the default driver
Creating demo_http_server_1 ... done
Creating demo_http_proxy_1  ... done
Creating demo_http_client_1 ... done
Attaching to demo_http_client_1
http_client_1  | "hello world"
http_client_1  | 
demo_http_client_1 exited with code 0

Note that while we start just http_client in the above command, all services are started. Why? Because, depends_on in Compose file guarantees desired services start order. Of course, start order may not be enough for the success of HTTP request, as http_server or http_proxy may not be available for some time after start. More advanced usage of depends_on may help. See this answer for more details.

Summary

You may also find below articles interesting:

Thanks for your attention! As always, feel free to share and comment.

Bonus: Watch recommended HTTP courses on Pluralsight:

Sign up using this link to get exclusive discounts like 50% off your first month or 15% off an annual subscription)

Purchase highly-rated Load Balancing with HAProxy: Open-source technology for better scalability, redundancy and availability in your IT infrastructure book on Amazon.