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.
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.
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
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 firstname.lastname@example.org #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.
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 email@example.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/aws/hosts file with the IP addresses of your local VM as well as your AWS instances.
Next, let's run the
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.
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.
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.