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 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:
- Go Docker CI in GitLab
- RabbitMQ cluster as a single Docker Swarm service
- Kubernetes StatefulSets Demo
- Dynamic Provisioning of Kubernetes Storage
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.