Setting up a Continuous Deployment pipeline with Docker and Travis

In the previous post we looked at a strategy for automating the deployment of single libraries/components.

In this entry I will describe how to setup a pipeline for a Continuous Deliver (CD) of an entire project, where every code commit which passes the CI test phase is automatically deployed into an environment, with changes that are immediately visible to the users.

This concept is a powerfull one, commiting your changes and seeing it built and deployed without any manual input is a huge time saver.

NOTE

We will assume Travis CI is used for CI, Github for version control and Dockerhub as the Docker image repository.
Obviously you will also need a Docker installation.
Yuu should be able to adopt these steps for different settings/repositoreis used.

Risking sounding opinionated I believe that Docker is to DevOps what GitHub is to development, which is why the right way to version Docker images is with the hashes corresponding to commits on the master branch.

If you follow the healthy practices of working with feature branches, squashing commits before merging them and never reverting commits on the master branch, you can immediately see the gains.
You can track back running containers to the merged features, immediately roll-back containers in your environments to a known point (should something break), finally if they pass the QA phase you can deploy them to the production and be sure that no unknown bugs are shipped.

So how exactly do we tag the Docker images with commit hashes?
We can get the hash of the last commit like this:

To automate the deployment we will always deploy the application image tagged as the latest.
However we need to keep one thing in mind - Docker’s latest tag is just a meta-tag, not a semantic version, and means:

either the last build ran without a specific version specified

or the build that was tagged as such

Therefore the best practice is to explicitely tag the last built with the latest tag:

Travis readily supports building Docker images and pushing them to the Docker repositories.
To build and deploy an image of your app to Dockerhub add the following settings to the .travis.yml file in the root of your projects repository:

We have went through the steps to build and deploy our containerized applications image to the Docker repository.
Now its time to automate updating of the running version of the app.

Watchtower is a service which automatically checks for, downloads and updates running containers.
The best part is that Watchtower itself is a Docker container.

NOTE

Unless you are really sure about your processes, CI, tests and coverage the “nightly builds” should rather be reserved for DEV or QA environments and not production.
But the great thing about this process is that a vetted image (versioned with a commit tag) can be easily and quickly deployed to production.

Watchtower needs to interact with the Docker API in order to monitor the running containers, which is why we mount host volume /var/run/docker.sock into the Watchtower container.
Cleanup means it will remove old images after updating.
We have also specified an interval of 300 seconds for checking for new image versions.
By default Watchtower will watch for and try to update all running containers.
For other configuration options you can consult the official documentation.

When it comes to the automated notifications I’m a big proponent of ChatOps.
Chat messages, unlike emails, are consumable by the whole team and especially in the case of alerts there is simply a bigger chance of someone noticing and reacting on them.

Watchtower can send notifications through a Slack webhook when containers are updated.
You simply need to pass two environment variables to it: