Ansible & Docker bringing back Simplicity & Power for modern web apps.

Ansible & Docker together makes deployment and building web apps so much more powerful. They bring back simplicity and power for building modern web apps. In this post, I will go into details of building a simple NodeJS web app locally and deploying the app to the AWS using Docker containers and Ansible automation tools.

Vagarant-Docker-Ansible story

Here is how I see the three technologies working together. Vagrant focuses on the management of your local VMs. Docker helps you with duplicating your OS, so that each copy can focus on a specific task. Ansible can empower and inject the duplications with code and logic to run. Together, you can have a modular system that can run independently of each other, but yet communicate in a managed way.

So What...

In the end of this post, here is how you should be able to use the Ansible to inject the code into your Docker container.

#run locally
ansible-playbook -i ansible/local/hosts -e ansible_ssh_port=40022 --private-key id_rsa.pub deploy.yml  
#run in AWS
ansible-playbook -i ansible/aws/hosts -e ansible_ssh_port=40022 --private-key id_rsa.pub deploy.yml  

Setup

Prerequisites

Install Vagrant with VirutalBox on your Mac or Windows. A Note on the versioning, make sure you download 4.2.* version of VirtualBox. Current version of Vagrant (1.4.3 as of this post) doesn't not support 4.3 version of VirtualBox.

Let's assume you are already have an empty Saucy (13.10) Ubuntu box in AWS and you have the IP Address for that.

Create an empty Ubuntu Saucy (13.10) box

#in your local machine
mkdir vagrant && cd $_  
vagrant init saucy64 http://cloud-images.ubuntu.com/vagrant/saucy/current/saucy-server-cloudimg-amd64-vagrant-disk1.box  
#edit the Vagranfile and uncomment the line "config.vm.network :public_network"
vagrant up  
vagrant ssh  
id addr show #get your IP Address here  
exit  
#make sure you can connect to the box through the IP
ssh vagrant@192.168.2.24  
#if there was any error check the selected Bridge Connection and make sure you have already added the default ssh key https://github.com/mitchellh/vagrant/tree/master/keys for Vagrant to the ssh keys through ssh-add command.

Now that we can connect to the Vagrant Box. Let's install Ansible on your local machine (Not the VM) and configure your boto module for the AWS.

Installing Ansible

sudo pip install paramiko PyYAML jinja2 httplib2 boto ansible  
cat > ~/.boto  
[Credentials]
aws_access_key_id = MY.KEY.HERE  
aws_secret_access_key = THIS.IS.SECRET.KEY  

Let's setup the barebone Saucy box with Docker through Ansible

git clone git@github.com:aminjam/docker-ansible.git  

In the repo you will find the basic folder strucure as well as playbooks to run, build, and deploy your web app. Make sure you modify ansible/local/hosts and ansible/aws/hosts file with the IP addresses of your local VM as well as your AWS instances.

Next, let's run the setup-saucy.yml and docker-node.yml against the VM.

ansible-playbook -i ansible/local/hosts -u vagrant playbooks/setup-saucy.yml  
ansible-playbook -i ansible/local/hosts -u vagrant playbooks/docker-node.yml  

These two playbook will bascially update the system, install Docker, and kick-off the Docker with an instance of my previusly build container with a basic installation of NodeJS. You should now have port 40022 open for SSH into the NodeJS container and just deploy your application logic. Later I will do another post on how to build the NodeJS container.

Next, let's deploy the our Node app to this container.

chmod 600 id_rsa*  
ssh-add id_rsa  
ansible-playbook -i ansible/local/hosts -e ansible_ssh_port=40022 --private-key id_rsa.pub playbooks/deploy-node-app.yml  

If everything has gone well, you should be able to just

curl http:\\VM.IP.Address  
Hello World from ExpressJS and NodeJS  

This was easy. Ready to Build the AWS box!

ansible-playbook -i ansible/aws/hosts -u ubuntu --private-key myAWS.pem playbooks/setup-saucy.yml  
ansible-playbook -i ansible/aws/hosts -u ubuntu --private-key myAWS.pem playbooks/docker-node.yml  

Once the box is ready, as long as you have port 40022 open in the your Security Group to your IP address you should be able to run

ansible-playbook -i ansible/aws/hosts -e ansible_ssh_port=40022 --private-key id_rsa.pub deploy.yml  

That's it. We just built a barebone Saucy box to a powerful container that we can just deploy the code to and run it in the VM, and once we are ready, just ship the same code to EC2, and run.

Notes

I wouldn't recommend using this setup in production. You would have to secure your keys, and being able to store the docker containers in private repo would make things much more secure. As it stands, Docker is not production ready yet. Instead of manually entering the AWS instances IP Address you should use ec2.py in Ansible Doc to pull the instances dynamically.

Summary

Docker is opening doors to building web apps that was not possible previously. Empowering developers to think of building applications as layers, more on this here. Ansible on the other hand, helps us utilize the power of SSH in such a simple and accessible way that we can use it to the deploy anywhere. You don't have to use AWS, you can use any cloud service provider that gives you SSH access along with a barebone Ubuntu installation. Good luck, keep hacking at it, and let me know your thoughts.

comments powered by Disqus