Launch a Web Server on Docker Container using Ansible
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 -
- Configure Ansible on controller node.
- 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 -
- when there is no âdocker-ceâ package is already installed on managed node.
- 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
Thank you!!! for reading.
Any suggestions are most welcome!!!
GitHub Repository Link for my Ansible code