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. |
You 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.
You 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. You can exclude some domains of the SSL forcing using the superwhale configuration file (read comments in configuration file). You can exclude all direct ip traffic (when Host header isn't set) by adding none
to the domain exclusion list.
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
- Fork the project.
- Make your feature addition or bug fix.
- Commit, do not mess with version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull).
- Send me a pull request.
Jérémy SEBAN - Main contributor - (GitHub: https://github.com/HipsterWhale)