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/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
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 $ANSIBLE_VAULT;1.1;AES256 64373132363633396261373538646633336136323638313638313262393232666361663032373138 6432326539353665373662396335333534396434396430620a393130323633653136663835633463 38316332353938363139343038333066303437666139336562333064643162313930326164346434 3165323536353964310a616365663565373737643264653961643535306262666630623132393032 65333033623666306237323864646362623363663031623932653836616665663436646231346466 3962333935336432393861626261363536353439323166613031
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!