Ansible environment setup using Docker Containers and Deploying a WebApp on them using Ansible Playbook

Rakesh Jain
4 min readSep 2, 2020

Our goal is to set up an environment so that Ansible can execute Playbooks on multiple different target systems and to see how those target systems, applications and databases are installed and configured.

Docker makes it really easy for us.

This is only for those who are interested in learning this method using a docker. So you require a basic understanding of Docker.

This is how we’re going to set up the environment.

All we need is a single virtual machine. You don’t need multiple virtual machines because with docker we’re just going to power up multiple Docker containers and they will act as the target servers for Ansible.

So we need one Ansible Controller VM with Ansible. Obviously Ansible installed in it and with Docker installed in it. And what we’re going to do is we’re going to power up multiple different Docker containers and which will have a basic Ubuntu docker images with probably SSH enabled.

Ansible Controller details -

root@ansible-controller:~/docker_ansible# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
root@ansible-controller:~/docker_ansible# ansible --version
ansible 2.5.1
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.17 (default, Jul 20 2020, 15:37:01) [GCC 7.5.0]

So we will power up multiple different docker containers and these docker containers will be associated to Dockers internal network. That is by default 172.17.0 range.

So once we have this we are going to target Ansible Playbooks to these systems and these IP addresses.

First get our Docker image:- Image — ubuntu-ssh-enabled

The Docker file used to create the ubuntu-ssh-enabled Docker image is located here.

https://hub.docker.com/rakeshrhcss/ubuntu-ssh-enabled

FYI — It is based on the Docker documentation written here:
https://docs.docker.com/engine/examples/running_ssh_service/

https://gist.github.com/TroubleshooteRJ/353e3e7bc150a0570623c1afb26ea876

Testing of this image ->

Run the container:
docker run -it -d -P --name test_sshd rakeshrhcss/ubuntu-ssh-enabled

#docker port test_sshd 22
0.0.0.0:49154
Identify the Internal IP
#docker inspect test_sshd
Delete the test container after reviewing the image.#docker container stop $(docker ps -aq)
#docker container rm $(docker ps -aq)

Now create these containers again as our Ansible targets -

#docker run -it -d rakeshrhcss/ubuntu-ssh-enabled 
#docker ps
#docker inspect
Run above three commands twice and update the inventory file accordingly.root@ansible-controller:~/docker_ansible# cat inventory.txt
db_and_webserver1 ansible_host=172.17.0.2
db_and_webserver2 ansible_host=172.17.0.3
Check the connectivity from ansible controller root@ansible-controller:~/docker_ansible# ansible db_and_webserver* -m ping -i inventory.txt
db_and_webserver1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
db_and_webserver2 | SUCCESS => {
"changed": false,
"ping": "pong"
}

Test ssh connection to docker setups -
You can ssh as root on the container’s IP address (you can find it with docker inspect)
Username: root
Password: Passw0rd

root@ansible-controller:~/docker_ansible# ssh root@172.17.0.3
root@172.17.0.3's password:
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.15.0-54-generic x86_64)* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Tue Sep 1 19:52:29 2020 from 172.17.0.1root@c8e6c2782f31:~# logout
Connection to 172.17.0.3 closed.
root@ansible-controller:~/docker_ansible# ssh root@172.17.0.2
root@172.17.0.2's password:
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.15.0-54-generic x86_64)* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Tue Sep 1 18:37:33 2020 from 172.17.0.1root@e79d9bd0bb84:~# logout
Connection to 172.17.0.2 closed.

Download the below playbook to launch a web application on our docker targets -

https://gist.github.com/TroubleshooteRJ/76e8d80b6ff99d02d6b08aeb073625d6

Download app.py file to the same folder where your main playbook is there.

https://gist.github.com/TroubleshooteRJ/7cf6e2246d48dd17796259f7dbcc9376
root@ansible-controller:~/docker_ansible# wget https://gist.githubusercontent.com/TroubleshooteRJ/7cf6e2246d48dd17796259f7dbcc9376/raw/2e97715a3a1771f0f8308e5b391e3f1ebd628a70/app.pyroot@ansible-controller:~/docker_ansible# wget https://gist.githubusercontent.com/TroubleshooteRJ/76e8d80b6ff99d02d6b08aeb073625d6/raw/e9668c662703db91d043db54d6158034a7a3a433/deploy-webapp-single-playbook.ymlroot@ansible-controller:~/docker_ansible# ls
app.py host_vars inventory.txt playbook.yml deploy-webapp-single-playbook.yml

Have a look at the host variable files (host variable file name and hostname should be same)

root@ansible-controller:~/docker_ansible/host_vars# ls
db_and_webserver1.yml db_and_webserver2.yml
root@ansible-controller:~/docker_ansible/host_vars# cat db_and_webserver1.yml
ansible_ssh_pass: Passw0rd
ansible_python_interpreter: /usr/bin/python
root@ansible-controller:~/docker_ansible/host_vars# cat db_and_webserver2.yml
ansible_ssh_pass: Passw0rd
ansible_python_interpreter: /usr/bin/python

Run the main playbook now -

root@ansible-controller:~/docker_ansible# ansible-playbook deploy-webapp-single-playbook.yml -i inventory.txtPLAY [Deploy a Web Application] ***************************************************************************************************************TASK [Gathering Facts] ************************************************************************************************************************ok: [db_and_webserver1]ok: [db_and_webserver2]TASK [Install dependencies] *******************************************************************************************************************ok: [db_and_webserver1] => (item=[u'python', u'python-setuptools', u'python-dev', u'build-essential', u'python-pip', u'python3-pip', u'python-mysqldb'])[DEPRECATION WARNING]: State 'installed' is deprecated. Using state 'present' instead.. This feature will be removed in version 2.9.Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.ok: [db_and_webserver2] => (item=[u'python', u'python-setuptools', u'python-dev', u'build-essential', u'python-pip', u'python3-pip', u'python-mysqldb'])TASK [Install MySQL database] *****************************************************************************************************************ok: [db_and_webserver1] => (item=[u'mysql-server', u'mysql-client'])ok: [db_and_webserver2] => (item=[u'mysql-server', u'mysql-client'])TASK [Start mysql service] ********************************************************************************************************************[WARNING]: Consider using the service module rather than running service.  If you need to use command because service is insufficient you canadd warn=False to this command task or set command_warnings=False in ansible.cfg to get rid of this message.changed: [db_and_webserver2]changed: [db_and_webserver1]TASK [Create application database] ************************************************************************************************************changed: [db_and_webserver1]changed: [db_and_webserver2]TASK [create databse user] ********************************************************************************************************************changed: [db_and_webserver2]changed: [db_and_webserver1]TASK [install python dependencies] ************************************************************************************************************changed: [db_and_webserver2] => (item=flask)changed: [db_and_webserver1] => (item=flask)changed: [db_and_webserver2] => (item=flask-mysql)changed: [db_and_webserver1] => (item=flask-mysql)TASK [copy source code file app.py] ***********************************************************************************************************changed: [db_and_webserver2]changed: [db_and_webserver1]TASK [start webserver] ************************************************************************************************************************changed: [db_and_webserver1]changed: [db_and_webserver2]PLAY RECAP ************************************************************************************************************************************db_and_webserver1          : ok=9    changed=6    unreachable=0    failed=0db_and_webserver2          : ok=9    changed=6    unreachable=0    failed=0

Test the app connectivity -

root@labs-sca01-8-8-11:~/docker_ansible# curl 172.17.0.2:5000
Welcome!
root@labs-sca01-8-8-11:~/docker_ansible# curl 172.17.0.3:5000
Welcome!

Thats all!

We have successfully made use of light weight Docker containers to deploy our application instead of using separate VM’s.

Hope you like the tutorial. Please let me know your feedback in the response section.

Happy Learning!

--

--