Automated Nginx Reverse Proxy for DockerMar 25, 2014 · 4 minute read · Comments
docker nginx service golang docker-gen
A reverse proxy server is a server that typically sits in front of other web servers in order to provide additional functionality that the web servers may not provide themselves.
For example, a reverse proxy can provide SSL termination, load balancing, request routing, caching, compression or even A/B testing.
When running web services in docker containers, it can be useful to run a reverse proxy in front of the containers to simplify depoyment.
Why Use A Reverse Proxy With Docker
Docker containers are assigned random IPs and ports which makes addressing them much more complicated from a client perspsective. By default, the IPs and ports are private to the host and cannot be accessed externally unless they are bound to the host.
Binding the container to the hosts port can prevent multiple containers from running on the same host. For example, only one container can bind to port 80 at a time. This also complicates rolling out new versions of the container without downtime since the old container must be stopped before the new one is started.
A reverse proxy can help with these issues as well as improve availabilty by facilitating zero-downtime deployments.
Generating Reverse Proxy Configs
Setting up a reverse proxy configuration can be complicated when containers are started and stopped. Typically the configuration needs to be updated manually which is error prone and time consuming.
Fortunately, Docker provides a remote API to inspect containers and access their IP, Ports and other configuration meta-data. In addition, it also provides a real-time events API that can be used for notifications when containers are started and stopped. These APIs can be used to generate a reverse proxy config automatically.
docker-gen is a small utility that uses these APIs and exposes container meta-data to templates. Templates are rendered and an optional notification command can be run to restart the service.
Nginx Reverse Proxy for Docker
This example nginx template can be used to generate a reverse proxy configuration for docker containers using virtual hosts for
routing. The template is implemented using the golang text/template package. It uses a custom
groupBy template function to group the running containers by their
VIRTUAL_HOST environment variable. This simplifies iterating over the containers to generate a load-balanced backend and also enables zero-downtime deployments.
The template can be run with docker-gen using:
docker-gen -only-exposed -watch -notify "/etc/init.d/nginx reload" templates/nginx.tmpl /etc/nginx/sites-enabled/default
-only-exposed- Only use containers that have exposed ports.
-watch- After starting up, watch for docker container events and regenerate the template.
-notify "/etc/init.d/nginx reload"- Reload the nginx config after the template is generated.
templates/nginx.tmpl- The nginx template.
/etc/nginx/sites-enabled/default- Destination file.
This is the rendered template with two containers configured with
VIRTUAL_HOST=demo1.localhost and one with
Try It Out
I created a trusted build with this setup to make it easier to try it out:
Run nginx-proxy container:
$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock -t jwilder/nginx-proxy
Start your containers with a
VIRTUAL_HOST environment variables:
$ docker run -e VIRTUAL_HOST=foo.bar.com -t ...
If you need HTTPS, would like to run
docker-gen in a separate container from nginx,
Websocket support or other features, take a look at the
github project for more information.
Generating nginx reverse proxy configs for docker containers can be automated using the Docker APIs and some basic templating. This can simplify deployments as well as improve availability.
Update: There’s a few other posts with similar ideas and variations that are worth checking out:
- Using Nginx, Confd, and Docker for Zero-Downtime Web Update - Brian Ketelsen
- Docker Events - Michael Crosby
- Haproxy As A Static Reverse Proxy for Docker Containers - Oskar Hane