Swarm TCP proxy
This is a Docker image which is designed to act as a TCP load balancer service for another backend swarm service.
It supports the Proxy Protocol for passing through information about the original connection.
What's the problem?
Every service running on a Docker swarm cluster has its own virtual IP address. The service containers are getting IP addresses from an overlay network with private IP addresses.
As every connection is routed through an ingress network, a service container will see an address from the ingress network for each incoming connection. It is thus unable to find out the real remote address.
As a workaround, the service can publish a port directly on the host. As this is only effective on the host the container is running on, the service has thus to be made global so it will be started on every host in the cluster.
For cases where this is not a feasible solution, Swarm TCP proxy comes into play.
How does it work?
Swarm TCP proxy is deployed as a global service, i.e. on all nodes in the cluster. As each instance is just a HAProxy instance, this has quite a small footprint.
It will forward each incoming connection to the virtual IP of the real service, which is then routed to the final container by Docker swarm itself.
In order to for the container to see the original remote address, Swarm TCP proxy uses the Proxy Protocol.
This means that the deployed application has to support the Proxy Protocol as well. See this introductory post for which software already supports the protocol.
Usage
See the supplied docker-compose.yml for an example. It uses the sample proxy-responder service which just returns the remote IP and closes the connection.
Example output:
$ docker-compose up -d
$ telnet localhost 8000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Hello, 192.168.80.1:37174
Connection closed by foreign host.
The example proxy runs on port 8080.
Configuration
The proxy is able to front multiple backend services listening at different addresses. It is configured through some mandatory ENV variables:
SERVICES
: a list of<SERVICE>:<PORT>
combinations which should be proxied, separated by spaces
The proxy will listen on the same port as each given service.
Other settings:
DISABLE_PROXY_PROTOCOL
: do not use the proxy protocol (just forward data)CONNECTION_TIMEOUT
: connection timeout to client as well as server (default: "5m")
Deprecated syntax
With the deprecated syntax, the proxy will front a single service while listening on port 8000
.
SERVICE_NAME
: name of the connected Swarm serviceSERVICE_PORT
: port on the service which should be proxied