Configure Apache Web-Server in Docker Container using Ansible-Playbook

vimal. D
8 min readMay 10, 2024

--

In this article we gonna use one of the most popular DevOps tool i.e. Ansible. We gonna integrate Ansible with Docker to launch a Web-Server. Before we go to the practical part let’s first we should know what is Docker ? What is Ansible ? How to install ? How Ansible work ? So lets start.

What is docker ?

Docker is a containerization tool. Using Docker we can launch the entire environment for our application server just in 1 second. Docker run in a isolation world so it is very secure to use for application server.

What is Ansible ?

Ansible is an open source IT configuration management (CM) and automation platform, provided by Red Hat. It uses human-readable YAML templates so that users can program repetitive tasks to occur automatically, without learning an advanced language.

We have 2 ways to do Configuration :

  1. Manual : This is typically a old traditional configuration way in which user have to do all work manually and where manual part comes there would a high possibility of errors and mistakes.
  2. Automation : We can do Automatic configuration in 2 way :

a. We have a traditional scripting approach were we use imperative language like python we have, In this we have to mention/tell How to do ? and What to do ?

b. We have a newer scripting approach were we use declarative language like Ansible we have, In this we have to mention/tell What to do ? and amazing thing is that Ansible know how to do ? which makes Ansible very intelligent.

How Ansible Work ?

System were we write/run a code of Ansible is called Controller Node. System which Ansible configure is called Managed Node. For this practical I am using 2 VM of REHL-8 OS, one for Controller Node and other one is for Managed Node. By sitting at 1 single place anywhere in the world you are controlling the Node (Managed Node).

This is my Controller Node !

This is my Managed Node !

make sure they both PING

Now lets move on to Configuration

Lets Setup ENV — Controller Node

install python3

yum install python3 -y

Check it

python3 -V

Install Ansible

pip3 install ansible

Check it

ansible --version

Creating Inventory

The system which Ansible manage is inventory. So we have to provide inventory to Ansible to contact managed node. Inventory is a database of IP, username and password.

Go to Desktop and Create a inventory file , you can give your file name

nano filename.txt

Inside the inventory give the SSH details

ManagedNodeipaddress ansible_ssh_user=root ansible_ssh_pass=yourpassword

Now we created the inventory in Desktop for Ansible but Ansible don’t know the location of this inventory. So we have to create a Ansible configuration file in which we have to give location of this inventory. Whenever Ansible run any command it always first go to this config file and then run any command. We have to create a Ansible name directory in /etc directory, in Ansible directory we will create Ansible.cfg file. As shown below.

mkdir /etc/ansible
nano /etc/ansible/ansible.cfg

here we need to write the conf code for ansible

[defaults]
inventory = your path to inventory file.txt
ansible_host_key_checking=FALSE

Check it working or not , using the following command

ansible all --list-hosts

here we see our Managed Node. Ansible Configuration file successfully created and now ansible know the location of inventory. Now to connect to managed node Ansible by-default use SSH protocol. To enable SSH protocol in controller node we need 2 packages i.e. epel-release and sshpass. First we need to install epel-release package which configure yum and give us extra packages with sshpass. Run below command to install this 2 packages.

yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
yum install sshpass -y

Now we will ping the managed node from controller node. If it is pinging we can configure anything in managed node. So lets check the connectivity.

ansible all -m ping

now we have successfully setup of ENV Controller Node ,

Now lets do a little test so we can verify our ansible is working properly for that go to Managed Node and delete the fire fox and reinstall through ansible Controller Node

to delete the fire fox in the Managed Node

rpm -q firefox
yum remove firefox -y

Now go to Controller Node and give the following command to install fire fox

ansible all -m package -a "name=firefox state=present"

now go back to Managed Node and check its done

rpm -q firefox

Our task is complete and ansible is working properly

Now let’s Configure docker in Managed Node and deploy Apache Web-Server in docker container. We will use Ansible playbooks for this practical.

Ansible Playbooks are one of the core features of Ansible and tell Ansible what to execute. Playbooks are the files where Ansible code is written. Playbooks are written in YAML format. YAML stands for Yet Another Markup Language. They are like a to-do list for Ansible that contains a list of tasks. Playbooks contain the steps which the user wants to execute on a particular machine(Managed Node). Playbooks are run sequentially.

Create the play book , use following command

nano filename.yml

here in this file we need to give the process what we wanna do in the Managed Node

→ Configure Docker

Here we are Configuring Docker Repository and then we pass a command to install docker with community edition (ce).

- hosts: "Managed_Node1"
tasks:
- name: Configuring Docker Repository
yum_repository:
name: Docker
description: "Docker Repo"
baseurl: "https://download.docker.com/linux/centos/docker-ce.repo"
gpgcheck: no
register: x
- name: Checking Configuration Status
debug:
var: x.failed
- name: Installing Docker
package:
name: "docker-ce-18.06.3.ce-3.el7.x86_64"
state: present
register: y
- name: Checking Install Status
debug:
var: y.failed

→ Start and Enable Docker Services

Here we pass a command to start Docker Services in managed node.

- name: Starting Docker Daemon
service:
name: docker
state: started
enabled: yes
when: y.failed == false

→ Pull the httpd server image from the Docker Hub

Here we pass a command to pull the httpd image from docker hub. Before we pull the image we need a docker-py package otherwise it won’t pull the image because for pulling it require some python libraries (pre-requisite).

- name: Install 
command:"yum install python3 -y"
- name: Install
command: "pip install docker-py"
- name: Pull a Docker Image
docker_image:
name: httpd
tag: latest
source: pull
register: z
- name: Checking Pull Status
debug:
var: z

→ Create Persistent Volume to mount with docker container.

Here first we are creating a persistent volume in managed node, after that we are copying the developer code in it.

- name: Creating a Persistent Volume Dir
file:
path: "/root/pv"
state: directory

- name: Copying the HTML code in the Directory
copy:
src: "/root/Desktop/index.html"
dest: "/root/pv"

→ Run the httpd container and expose it to the public.

Here we are launching the HTTPD container and we expose the webserver so that client can access the webserver. We also mount the volume which we created in Step-4 with container, so that if any container get terminated / fail we won’t lose data.

- name: Launching an HTTPD Container
when: z.failed == false
docker_container:
name: apache-server
image: httpd
state: started
exposed_ports:
- "80"
ports:
- "8888:80"
volumes:
- /root/pv:/usr/local/apache2/htdocs

Hope you got an idea about the code

This is my complete Ansible playbook for for Configure Docker and Deploy Web Server in Docker Container:

- hosts: "all"
tasks:
- name: Configuring Docker Repository
yum_repository:
name: Docker
description: "Docker Repo"
baseurl: "https://download.docker.com/linux/centos/docker-ce.repo"
gpgcheck: no
register: x

- name: Checking Configuration Status
debug:
var: x.failed

- name: Installing Docker
package:
name: "docker-ce-18.06.3.ce-3.el7.x86_64"
state: present
register: y

- name: Checking Install Status
debug:
var: y.failed

- name: Starting Docker Daemon
service:
name: docker
state: started
enabled: yes
when: y.failed == false

- name: Install
command: "yum install python3"

- name: Install
command: "pip install docker-py"

- name: Pull a Docker Image
docker_image:
name: httpd
tag: latest
source: pull
register: z
- name: Checking Pull Status
debug:
var: z

- name: Creating a Persistent Volume Dir
file:
path: "/root/pv"
state: directory

- name: Copying the HTML code in the Directory
copy:
src: "/root/Desktop/index.html"
dest: "/root/pv"

- name: Launching an HTTPD Container
when: z.failed == false
docker_container:
name: apache-server
image: httpd
state: started
exposed_ports:
- "80"
ports:
- "8888:80"
volumes:
- /root/pv:/usr/local/apache2/htdocs

finally you have add your html code in your specified path in code — if you don't have code you can use my code in the github repo bellow

Lets run this Ansible-playbook with given below command:

ansible-playbook yourfilename.yml

It will give the output like this:

docker
file copying

Web-Server is Successfully deployed in docker container. Lets go to the Managed node and check.

use the following command in the Managed Node

systemctl status docker

Now lets check the output by give the ip of Managed Node in our host system web browser

ipaddress:portnumber 

Here we can see our site running successfully

You can get code of this task in my git hub account:(⌐■_■)

LinkedIn (⌐■_■)

Donotopen^_^

--

--

vimal. D

I'm Vimal, currently pursuing a BSc in Computer Science with a focus on Cloud Computing and Information Security.