Technologies

As before we can install docker for our platform of choice. We will be using docker, and docker-machine utilities to create our services.

We will use Docker Flow: Swarm Listener, Proxy, and Let's Encrypt for our frontend services. These will provide our service discovery, reverse proxy and load balancing, and SSL services respectively.

Docker Flow: Swarm Listener

Docker Flow: Swarm Listener is a companion to Proxy that updates the configuration of the proxy dynamically as new services are added to the cluster. For example, if we have both Proxy and Swarm Listener running, and we add our new website to the cluster, Swarm Listener will automatically update the Proxy config so that we can actually access our website.

Docker Flow: Proxy

Docker Flow: Proxy is the reverse proxy that we will use to route and load balance traffic within our cluster. This docker image uses HAProxy in the background to load balance. Another benefit to using this proxy is that it has built in support for swarm mode so no special configuration is necessary.

Docker Flow: Let’s Encrypt

Docker Flow: Let’s Encrypt is another companion project to Proxy that uses the Let’s Encrypt certificate authority to get free SSL certificates for HTTPS. The catch with these certificates is that they are only valid for 90 days. This is the intended behaviour as they don’t want expired domains and certificates out on the internet. This companion gets around this limitation be automatically setting up an auto-renew cron job once it starts. The certificates themselves are only renewed once they are 60 days or older.

Frontend Services

Now we will start with creating the frontend services. These services can be created via individual docker commands or all together using a docker-compose.yml file. We will be going over both methods. First we will have a look at the docker commands to learn the details of what is going on with the services. Then we will create a single YAML file to deploy our entire stack with one command.

Swarm Listener

First we have to start the Swarm Listener which will provide us with service discovery features. We can start the listener with the following command:

The above command creates a service named swarm-listener. It uses the main network that we created in the previous post. We also mount and bind the docker.sock socket and assign the HAProxy reconfigure and remove URLs to the DF_NOTIF_CREATE_SERVICE_URL and DF_NOTIF_REMOVE_SERVICE_URL environment variables. Lastly we also added a constraint to the service which restricts it to manager nodes.

Proxy

Next we will start the reverse proxy which will also load balance the incoming requests. We can start the proxy with the following command:

Here we name our container proxy. We publish ports 80, and 443 for web access to our proxy. We also publish port 8080 so the swarm-listener can reconfigure the proxy configuration when we create new services. Like before we tell the container to use the main network and restrict it to manager nodes using the node.role == manager constraint. Lastly we use the MODE and LISTENER_ADDRESS environment variables to inform the container that it is working in a swarm and which container is the listener.

Let’s Encrypt

A few caveats to using this companion is that there must only be one instance of it on the swarm, it must run on the same node (you can move it to a different node, but it must only stay on that node), and there must be a folder created on the node that this runs on.

So to work with this companion, we first have to pick which node we want to run it on. We can do that using the following the command:

docker node ls

We pick a machine from the resulting list and copy its id. Let’s go with manager-1.

Second we have to create the /etc/letsencrypt folder on the machine we want the companion to run on.

Here we use the labels to notify the swarm-listener and the proxy to use the let’s encrypt companion. We use environment variables here to tell the container which domain we want to secure, how many domains we are securing, the email to use for let’s encrypt, the container name of the reverse proxy, and how often we want to renew the certificate using cron syntax. As before we use the main network and we bind the directory we created earlier. We use the node.id constraint to make sure it only starts on that node. Lastly we use the replicas option to make sure there is only one instance of this companion running.

Note: The domains you specify must be registered domains. Local domains will not work. For local testing we can use insecure HTTP requests.

Docker Compose Config

If web don’t want to individually start each service, we can deploy an entire stack. Docker 1.13 has the ability to use docker-compse.yml files to deploy whole stacks of services at once. To use this feature we copy the following to docker-compose.yml.

This compose file defines all of same environment variables, labels, constraints, and volumes as before. With one exception, the compose file uses a named volume in place of /etc/letsencrypt. This is more convenient because we don’t have to create the directory on the host.