A custom reverse proxying solution based on HAProxy for a docker network infrastructure.
1.2K

Logo by Camille BRIZARD
This project is licensed under the terms of the MIT license.
Last version : 2.1.0
Docker introduced Docker Networks with version 1.9. With that update you can now have multiple web servers linked to the same network and a reverse proxy in front of them all without having to manage links manually. First, I was using HAProxy to do this role but HAProxy wasn't flexible enough : I was facing an issue, sometimes my containers weren't running while I was starting up my reverse and because HAProxy force name resolving at startup it was crashing almost every time. So I decided to create a system that add a smart layer upon HAProxy using a simple ruby script.
It uses alpine as a base distribution to provide a lightweight image. It includes ruby (with 1 gem : FileWatcher) and HAProxy, that's all. At startup, SuperWhale will launch /bin/superwhale : the main process of the container.
superwhale will search for services inside the /etc/superwhale.d folder, create HAProxy configuration and then start HAProxy. It will also watch for file modifications inside /etc/hosts or /etc/superwhale.d and will semi-gracefully reload HAProxy if there is any.
A service is the superwhale representation of a backend webserver that needs to be reverse proxied. To declare a service create an YAML file and put it inside the /etc/superwhale.d folder. For instance :
git:
domain_name: git.mydomain.tld
backends:
- host: git_container
port: 80
options:
- option forwardfor
- http-request set-header X-Client-IP %[src]
- http-request set-header Host git.mydomain.tld
Will output this inside HAProxy configuration ONLY if a git_container is present on the relevant docker network :
[...]
frontend public
[...]
acl host_git hdr(host) -i git.mydomain.tld
use_backend git_backend if host_git
backend git_backend
server git1 git:80
option forwardfor
http-request set-header X-Client-IP %[src]
http-request set-header Host git.mydomain.tld
[...]
You can define multiple backends to create a load-balanced backend and the load-balancing algorithm used between them.
Here is an exhaustive list of what you can define for a service :
| Option | Type | Usage |
|---|---|---|
| domain_name | string | Define the domain name used to determine the backend |
| backends | {host: 'hostname',port: port_int}[] | Address of the backend server |
| balance | string | Define the load-balance algorithm for the backend pool |
| options | string[] | Options added to the backend block |
| is_default | bool | If true, add default_backend with this backend. Only one service can define this option. |
superwhaleYou can tune superwhale configuration using the its configuration file : /etc/superwhale.d/configs/superwhale.yml. Here is the default version of this file :
# Redirect all HTTP traffic to its HTTPS counterpart
force_ssl: false
# If you want some domains/sub-domains to not be ssl forced, uncomment this
#ssl_noforce_domain:
# - my.domain.tld
# - [...]
# Change the log level : debug, info (default) and warning
log_level: info
When reloading, Superwhale will do a soft-stop before restarting the process. There is a little time at startup when connections will be refused. That's why I called it "Semi-gracefull" reload.
Here is what HAProxy documentation says about soft-stop :
2.4) Soft stop
--------------
It is possible to stop services without breaking existing connections by the
sending of the SIGUSR1 signal to the process. All services are then put into
soft-stop state, which means that they will refuse to accept new connections,
except for those which have a non-zero value in the 'grace' parameter, in which
case they will still accept connections for the specified amount of time, in
milliseconds. This makes it possible to tell a load-balancer that the service
is failing, while still doing the job during the time it needs to detect it.
haproxy.cfg headerYou can modify the header.cfg file in /etc/superwhale.d.
You can use HTTPS by simply adding certificate file : /etc/superwhale.d/https.pem. This certificate is the concatenation of the certificate and the private key :
$ cat server.crt server.key > /etc/superwhale.d/https.pem
If you want to redirect all traffic to HTTPS, switch the force_ssl boolean to true inside the superwhale configuration file.
There is two way of using this container :
While launching the container, use the -v argument :
docker run -d \
-v /mnt/volumes/superwhale/:/etc/superwhale.d \
-p 80:80 -p 443:443 --net=dockernet ingensi/superwhale
Create a Dockerfile and inherits from ingensi/superwhale :
FROM ingensi/superwhale:latest
COPY ./service1.yml /etc/superwhale.d/service1.yml
Jérémy SEBAN - Main contributor - (GitHub: https://github.com/HipsterWhale)
Content type
Image
Digest
Size
8.6 MB
Last updated
over 10 years ago
docker pull ingensi/superwhale