Apache web server on Docker Container using Ansible

Launch a Web Server on Docker Container using Ansible

Shashi Kant

--

Task -

Write an Ansible PlayBook that does the following operations in the managed nodes -

🔹 Configure Docker package
🔹 Start and enable Docker services
🔹 Pull the httpd server image from the Docker Hub
🔹 Run the httpd container and expose it to the public
🔹 Copy the html code in /var/www/html directory and start the web server

prerequisites -

  1. Configure Ansible on controller node.
  2. Controller Node and managed nodes should have network connectivity.

So, lets get started

Configure Controller node inventory file. Add all the hosts (managed nodes) in it.

[docker]
192.168.43.39 ansible_ssh_user=root ansible_ssh_pass="<password or key name of node/host>"

here, I am adding only one node. but we can add as many as we want to configure as web server

Ansible Playbook

Now time to write Ansible Playbook for configuring docker for Apache Web server.

so, create a workspace in controller node. start writing ansible playbook and extension should be “.yml or .yaml” of file, because we write playbook in yaml language.

- name: "Configure Docker"
hosts: docker
gather_facts: yes
vars:
- image: "httpd"
- webpages: "index.html"
- webpath: "/root/web/"
tasks:
- name: "Check Docker package Installed or Not"
shell: "rpm -q docker-ce"
register: checkd
ignore_errors: yes

- name: "Debug check docker package"
debug:
var: checkd

here, I added my hosts (managed nodes) as ‘docker’ as I write in inventory file. and created some variables which we gonna use later in playbook.

First I have checked whether the docker package is already installed or not on managed node. If ‘docker’ package is not installed then it will give us error and that error we can use further as a condition in playbook which we will see ahead in playbook.

Configure yum repository and Install docker-ce package

If above code give error then this code will run and configure yum repository to Install docker-ce package. And if ‘docker-ce’ package is already installed on managed node then these both steps will be skipped.

      - name: "configure yum for docker-ce"
yum_repository:
name: Docker
description: Repository for Installing Docker-ce package
file: docker
baseurl: https://download.docker.com/linux/centos/7/x86_64/stable/
gpgcheck: no
when: ( checkd.failed == true or checkd.rc != 0 )
register: yum
ignore_errors: yes

- name: "Debug yum configuration"
debug:
var: yum

- name: "Install docker-ce package"
shell: "{{ ansible_pkg_mgr }} install docker-ce --nobest -y"
when: ( checkd.rc != 0 or checkd.failed == true ) and ( yum.state == "present" )
register: installdocker

- name: "Debug Install Docker"
debug:
var: installdocker

Here, I have used ‘shell’ module of ansible because ‘yum’ or ‘dnf’ module does not have any ‘nobest’ option, [This is one of limitation of Ansible].

Installing of ‘docker-ce’ package depends on two conditions -

  1. when there is no ‘docker-ce’ package is already installed on managed node.
  2. And when ‘yum’ repository is created successfully.

Start and enable Docker services

      - name: "start Docker services"
service:
name: docker
state: started
enabled: yes
register: srvc

- name: "Debug Docker Service"
debug:
var: srvc.changed

From this block of code docker service will start and enable on the managed nodes.

Install ‘docker’ python library

For pulling any docker image from ‘hub.docker.com’ or doing any thing on docker container we need ‘docker’ or ‘docker-py’ library on managed node. otherwise any of docker related ansible module will not work on managed node.

      - name: "Check Docker python Library is Installed or Not"
shell: "pip3 list | grep docker"
register: dockerLibrary
ignore_errors: yes

- name: "Debug docker Library"
debug:
var: dockerLibrary

- name: "Install python36 package"
package:
name: python36
state: present
register: ipython
when: dockerLibrary.rc != 0 or dockerLibrary.failed == true

- name: "Debug python36 package"
debug:
var: ipython

- name: "Install docker library"
pip:
name: "docker"
when: ( dockerLibrary.rc != 0 or dockerLibrary.failed == true ) and ipython.rc == 0

Like before I checked docker package, and if it is not installed then I write yum module and package module, likewise here also first I checked for ‘docker’ python library and if it is not installed then first it install ‘python36’ package and then it will install ‘docker’ library.

Pull ‘httpd’ Docker Image.

      - name: "Pull Docker Images"
docker_image:
name: "{{ image }}"
source: pull

variable we created at the top of playbook ‘image’ we have used here. and this code will pull ‘httpd’ image from hub.docker.com. this is why all our managed nodes should have Internet connectivity.

Copy Web Pages

create a new file in your workspace. name it any thing and give extension ‘.html’. I named my file as ‘index.html’

<h1>Welcome!!! to my Web Server</h1><h2>Hello This is Shashi Kant</h2>

<h3>This is Docker Container from Ansible</h3>

I write these three line for testing.

      - name: "Create Directory to copy web pages"
file:
path: "{{ webpath }}"
state: directory
register: mkdir

- name: "Debug create Directory"
debug:
var: mkdir

- name: "Copy Web Pages"
template:
src: "{{ webpages }}"
dest: "{{ webpath }}"
register: copywebpages

- name: "Debug Copy web pages"
debug:
var: copywebpages

Now add this code in playbook for copying web pages.

and finally launch Docker Container.

Launch Docker Container

Now finally write code for launching docker container. and expose it to public world. as they also can access your website.

      - name: "Launch Docker Container"
docker_container:
name: ansibleWebContainer
image: "{{ image }}"
state: started
exposed_ports: "80"
ports: "8080:80"
volumes: "{{ webpath }}:/usr/local/apache2/htdocs/"
network_mode: bridge
restart: yes
restart_policy: always
when: mkdir.failed == false and copywebpages.failed == false

using docker_container module we can launch docker container. here I used ‘httpd’ Images. and expose it to public world on port no. 8080. and it is using volume of managed node where we have copied our web pages.

Used ‘bridge’ type network as ‘network_mode’ in container, it will provide network connectivity in docker container.

I used ‘restart’ and ‘restart_policy’ here because it will give me some little management of container. like if my container goes down due to some reasons then docker will automatically launch same new container for me, with same web pages. until I manually delete or stop this container.

and this play run only when our above code of copying web pages and creating directory will run successfully.

Now, Finally Run Ansible Playbook.

ansible-playbook <name_of_ansible_playbook.yml># here I used 'docker.yml'
# ansible-playbook docker.yml
Run Ansible Playbook
Configure yum and Install ‘docker-ce’ package if not Installed and skip these plays if already configured and Installed
Check ‘docker’ python library is installed or not
If ‘docker’ python library is not Installed then Install ‘python36’ package and Install ‘docker’ library otherwise skip these plays. And Create a directory to store web pages
Copy web pages to the managed node.
Finally Launch the Web Server on Docker Container
Checking Docker services before and after running playbook.
‘docker ps’ command to see the active docker containers…here we can see this container is launched by Ansible with httpd image and expose to port no. 8080
we can check our web server by using ‘curl’ command
or, we can check our web server on web browser (GUI)

--

--