Provision Docker on multiple OS using Ansible

Docker enables faster software delivery cycles. Docker containers make it easy to put new versions of software, with new business features, into production quickly. This article will help you to create your own Ansible Role to launch docker in 2 widely used OS Families: Debian & RedHat and then configure a web server on both of them.

Daksh Jain
6 min readOct 25, 2020
Ansible + Docker

This is the era of speed. Faster delivery cycles, faster deployments, faster reach to the market, even faster rollbacks are what the market demands.

Docker enables faster delivery of software. The main aim of launching an OS is so that we can run a program. Docker helps the user to focus on the program rather than focus on the installation of the OS. Docker is a very much required tool in the field of DevOps and has increased the pace at which companies deliver. Docker helps these companies using docker, to win at every stage.

They are an extra mile ahead, every time!

I have created this setup by following the below-mentioned steps:

  • Create an inventory file.
  • Create an Ansible configuration file.
  • Create an Ansible Role.
  • Put the files in the /tasks folder.
  • 1- the main file that will call the file to setup Docker in RedHat & Debian and then the common configurations.
  • 2- a file to setup Docker in RedHat.
  • 3- a file to setup Docker in Debian.
  • The main file to call this role in all entries in inventory.

Let’s start by building the code:

Step 1 — Inventory file

Inventory
[redhat]
192.168.56.101 ansible_ssh_user=root ansible_ssh_pass=redhat
[kali]
192.168.56.102 ansible_python_interpreter=/usr/bin/python3 ansible_ssh_user=root ansible_ssh_pass=toor

In the host group [redhat] I have specified the IP, username, and password of the VM with RedHat installed.

In the host group [kali] I have specified the IP, username, and password of the VM with Kali Linux installed. Kali has the OS Family — Debian. Additionally, I have also specified the python interpreter (python3) that Ansible will use in that OS.

Kali — Debian Family
RHEL8 — RedHat family

Step 2 — Ansible Configuration File

ansible.cfg

Step 3 — Create an Ansible Role

ansible-galaxy init docker
File Structure

Step 4 — Create a main.yml file here to call the role

- hosts: all
roles:
- role: docker

This file is working on all hosts in the inventory and calling the role docker.

Step 5 — Creating the tasks

Now go inside the tasks folder and create 2 files:

cd /etc/ansible/roles/docker
cd tasks
touch Debian-docker.yml
touch Redhat-docker.yml

main.yml is already present in the folder.
Now the folder looks like this =>

Step 5— Create Redhat-docker.yml

- name: add docker gpg key
rpm_key:
key:
https://download.docker.com/linux/centos/gpg
state: present
- name: Docker Yum Setup
yum_repository:
name: docker-repo
baseurl:
https://download.docker.com/linux/centos/7/x86_64/stable/
description: Docker yum repo setup
gpgcheck: yes
- name: Python 3 install
package:
name: python36
- name: Docker Module for Python
pip:
name: docker-py
- name: Install containerd.io
package:
name: containerd.io.x86_64
state: present
- name: Install docker
package:
name: docker-ce-18.09.1
state: present
  • rpm_key module is used to add the key signatures that will be check during gpgcheck while installing docker from an rpm package.
  • yum_repository module is used to set up the yum repository for docker installation. gpgcheck if set to yes, will verify the authenticity of the packages by checking the GPG signatures.
  • Then it is checked if the python3 module is installed correctly.
  • Then using pip module docker-py is installed. Ansible is written in Python, so is the docker module. This module makes uses of the docker-py Python library to manage containers via Ansible. It is a docker remote API and does everything the docker command does.
    To use Ansible’s docker module, you’ve to make sure the docker-py library is installed.
  • Due to some conflicts in RHEL8, I have preferred to install a particular version of containerd.io and docker-ce.
    Containerd is a container runtime that can manage a complete container lifecycle — from image transfer/storage to container execution, supervision, and networking. It is designed to be used by Docker and other container platforms that wants to abstract away syscalls or OS-specific functionality to run containers on Linux, Windows, Solaris, or other OS.
  • Then finally docker-ce version 18.09.1 is installed using the package module.

Step 6— Create Debian-docker.yml

- name: Add Docker apt key
apt_key:
url: "
https://download.docker.com/linux/debian/gpg"
state: present
- name: Add Docker repository
apt_repository:
repo: "deb [arch=amd64]
https://download.docker.com/linux/debian buster stable"
state: present
update_cache: yes
- name: Docker Module for Python
pip:
name: docker-py
- name: ensure old version are not there
package:
name:
- docker-engine
- docker.io
- docker
state: absent
- name: Install docker
package:
name: "docker-ce"
state: present
  • apt_key module is used to add the apt key signature that will verify the authenticity during the package installations.
  • Then using the apt_repository module an apt repository is set up for the installation of docker.
  • Then the docker-py module is installed using pip.
  • Then using the package module and state: absent old versions of packages are removed from the OS to ensure no conflicts.
  • Then finally using the package module docker-ce software is installed,

Step 7— Create main.yml

---
# tasks file for docker
- include_tasks: Redhat-docker.yml
when: ansible_os_family == 'RedHat'
- include_tasks: Debian-docker.yml
when: ansible_os_family == 'Debian'
- name: Create a directory if it does not exist
file:
path: /root/web/
state: directory
- name: copying the code
copy:
src: /var/www/html/
dest: /root/web/
- name: Docker service
service:
name: docker
state: started
enabled: yes
- name: pull httpd image
docker_image:
name: httpd
tag: latest
source: pull
- name: run http container
docker_container:
name: web_container
image: httpd:latest
detach: yes
tty: yes
interactive: yes
published_ports:
- 80:80
volumes:
- /root/web/:/usr/local/apache2/htdocs/
  • include_tasks module is used to include the other tasks based upon a condition: ansible_os_family.
    if
    family == RedHat call the Redhat-docker.yml file.
    if family == Debian call the Debian-docker.yml file.
  • After any of these files are called, the docker is successfully installed using the above-created files.
  • Then the common configurations that need to be done in both of the OS are specified here.
  • Using the file module a directory is created /root/web
  • Using the copy module the code from /var/www/html (in the controller node) is put in the folder /root/web (in the managed node).
  • Using the service module the docker services are started and enabled in the managed nodes.
  • Using the docker_image module an httpd image is pulled. It will be used to configure the node as a web server.
  • Finally using the docker_container module, the container is launched using the above-pulled httpd image.
    This module uses the docker-py SDK.

The equivalent docker command for the same will be:

docker run -dit                                                             --name web_container                                                       -p 80:80                                                                             -v /root/web/:/usr/local/apache2/htdocs/                                         httpd:latest

Now running the playbook -

cd /etc/ansible/roles/dockeransible-playbook main.yml
ansible-playbook main.yml

Final Output -

The output from Debian & RedHat

As can be seen, the demo webpage is accessible from both the Debian & RedHat IPs once the playbook completely runs.
192.168.56.101
192.168.56.102

What you learned -

  • Now you can successfully create your own customized roles in Ansible.
  • You can create your own role for setting up Docker on multiple OS.
  • Concepts and internals of Docker & containerd.

--

--

Daksh Jain

Automation Tech Enthusiast || Terraform Researcher || DevOps || MLOps ||