Docker + Ansible = Happiness!

A few months ago, I wrote a toy financial application in R language that scans NYSE and NASDAQ’s stocks, finds interesting patterns in a stock’s quote, generates a report, and sends it via email. It ran quite smoothly for a few months, but suddenly I became unsatisfied with how the infrastructure of the application was provisioned.

The dissatisfaction began when I heard about Docker.


Docker is a fantastic tool to containerize each process of an application. It allows you to create specialized containers that run a single process, and links together those containers to create the infrastructure of an application.

I decided to split the application in a few of Docker images:

  • A container based on busybox that holds the files produced by the application

  • madrossan/r-extended it’s the r-base image enhanced with useful R packages.

  • madrossan/tstock the application’s image that inherits from madrossan/r-extended and adds the application’s source file.

Unfortunately when developing this application, I found myself through several iterations of changing a Dockerfile of the images, rebuilding them, and deploying the application. It was painful to do manually, particularly because I have really little time to waste typing commands since I develop the application in my spare time.

To solve this automation problem I gave Fig a try because it looks promising and now it has officially joined Docker (with the name Compose), but I found out that it’s not exactly what I was looking for.

Get to know Ansible

I’ve always stared at configuration management systems like Chef or Puppet for a while, but I found them heavy since they are agent-based and with quite a steep learning curve.

Then I found Ansible. It’s a great agent-less tool to automate every aspect of an IT infrastructure in a simple way. The task of building the infrastructure and deploying the application are simply described by YAML files called “playbooks”.

Above, there’s my simple playbook. I don’t want to repeat paths in the application, in the Dockerfile and in the playbook, so for this specific case I decided to create the real application and Dockerfile from Jinja2 (the template engine used by Ansible) templates that are transformed in the actual files by the playbook’s execution. What I find amazing about Ansible is the plethora of modules in the “core” repository. My playbook uses Docker’s specific ones, a module to handle crontab entries, a module to render templates, and so on. You can also see that each task is described by a name that is really useful as documentation for anybody that reads or executes a playbook.

Among the several useful features of Ansible and additional tools, there is also Ansible Vault. It allows you to store data such as passwords and API keys in an encrypted file, so it’s safe to distribute the source code of an application without leaking data; have you ever heard about $5,000 Security Breach?

To create a new vault with the specified password and open the default editor:

$ ansible-vault create user-data.yml
Vault password:
Confirm Vault password:

A simple “cat” of the file reveals that it’s encrypted:

$ cat user-data.yml

I use the great Mailgun REST service to send emails with the generated report and obviously Ansible Vault is a secure way to store my Mailgun’s API key!

Written on April 3, 2015