There are a number of ways to deploy containers. You can use just Docker, Kubernetes, Microk8s, LXD and so on. In this guide, however, we are going to look at how to deploy docker containers with Ansible.

Ansible is a simple tool for IT automation. It uses ssh to run commands on remote servers. Ansible has been used in cloud automation, application deployment and configuration management among others. Ansible uses both playbooks and ad-hoc commands to run commands and deploy applications on remote servers.

Playbooks are yaml files that systematically define the remotes servers and the tasks to be performed. Ad-hoc commands on the other hand are single-line commands run on the terminal. We are going to use playbooks to deploy containers on remote servers.

My Lab Setup

In my set up, I have three servers running Ubuntu 20.04. One server has Ansible installed while the other two servers are the remote nodes where Docker containers will run.

  • Ansible-server 192.168.50.2
  • webserver-01 192.168.50.3
  • webserver-02 192.168.50.4

Install Ansible on Ubuntu 20.04

We need to install ansible on one of the servers. The Ansible server should reach the other remote servers via ssh. We will therefore generate ssh key and copy the public key to the remote servers. Ansible server should also have a user with root privileges. To install Ansible on Ubuntu 20.04, please run the below commands:

sudo apt-get update
sudo apt-get install ansible

You can confirm that ansible us installed by checking on the version

$ ansible –version
ansible 2.9.6 
 config file = /etc/ansible/ansible.cfg 
 configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] 
 ansible python module location = /usr/lib/python3/dist-packages/ansible 
 executable location = /usr/bin/ansible 
 python version = 3.8.5 (default, Jul 28 2020, 12:59:40) [GCC 9.3.0]

Generate ssh key

We need to generate ssh and copy the public key to the remote servers.

ssh key-gen

Provide the location to save your ssh keys and choose whether to use a passphrase. For my case, I choose the default location. Once saved, copy Public key to the remote servers with the below command:

ssh-copy-id [email protected]

Ensue that you can ssh to your remote servers from Ansible server using ssh key. Also confirm you can reach all your remote servers through ping. For this we will need to define our remote servers in Ansible hostsfile. Ansible configuration files are in /etc/ansible

$ ls -alh
drwxr-xr-x  2 root root 4.0K Nov  6 15:29 . 
drwxr-xr-x 93 root root 4.0K Nov  6 13:48 .. 
-rw-r--r--  1 root root  20K Mar  5  2020 ansible.cfg 
-rw-r--r--  1 root root  982 Dec 18  2018 hosts

Rename the hosts file and create another one as below

sudo mv /etc/ansible/hosts /etc/ansible/hosts.orig
sudo vim /etc/ansible/hosts

Add your remote servers so that your file appear as below:

[webserver]
192.168.50.3
192.168.50.4

Now ping all the servers with ansible command as below:

$ ansible -m ping all 
192.168.50.3 | SUCCESS => { 
   "ansible_facts": { 
       "discovered_interpreter_python": "/usr/bin/python3" 
   }, 
   "changed": false, 
   "ping": "pong" 
} 
192.168.50.4 | SUCCESS => { 
   "ansible_facts": { 
       "discovered_interpreter_python": "/usr/bin/python3" 
   }, 
   "changed": false, 
   "ping": "pong" 
}

Install Docker CE on Ubuntu 20.04 with Ansible

Since we need Docker for deploying containers, we are going to install Docker CE on our remote servers. We need to create a playbook on our ansible server that will install Docker CE on our remote servers. The playbook will do the following:

    • Ansible prefers aptitude package manager over the default apt.
    • Install the required system packages such as python3-pip, curl, and others. 
    • Install Docker GPG APT key to the system and add the official Docker repository to the apt source. 
    • Install Docker on the remote machines. 
    • Install Python Docker module via pip.

Create playbook file with the following command:

sudo vim /etc/ansible/docker-playbook.yml

Add the following content to install Docker CE using Ansible

---
- hosts: all 
  become: true 
  tasks: 
          - name: Install aptitude 
            apt: name=aptitude state=latest update_cache=yes force_apt_get=yes 

          - name: Install required dependencies 
            apt: name={{item}} state=latest update_cache=yes 
            loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools'] 
          - name: Add Docker GPG apt Key 
            apt_key: 
                    url: https://download.docker.com/linux/ubuntu/gpg 
                    state: present 

          - name: Add Docker Repository 
            apt_repository: 
                    repo: deb https://download.docker.com/linux/ubuntu focal stable 
                    state: present 

          - name: Update apt and install Docker CE 
            apt: update_cache=yes name=docker-ce state=latest
          - name: Install Docker Module for Python 
            pip: 
                    name: docker

Create Docker container using Ansible

We have installed Docker CE on our remote hosts using Ansible. Next we are going to deploy an Nginx container using ansible. Define the variables that will be used in creating the container as below.

---
vars:
	create_containers: 1
	default_container_name: nginx 
	default_container_image: nginx

Pull image from Docker hub.

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

We then need to define container deployment in our playbook as below:

- name: Create default containers 
     	docker_container: 
       		name: "{{ default_container_name }}{{ item }}" 
       		image: "{{ default_container_image }}" 
       		state: present 
     	with_sequence: count={{ create_containers }}

Our Playbook should finally look as below:

---
- hosts: all
  become: true
  vars:
           create_containers: 1
           default_container_name: nginx
           default_container_image: nginx
          
  tasks:
           - name: Install aptitude
             apt: name=aptitude state=latest update_cache=yes force_apt_get=yes

           - name: Install required dependencies
             apt: name={{item}} state=latest update_cache=yes
             loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools' ]


           - name: Add Docker GPG apt Key
             apt_key:
                     url: https://download.docker.com/linux/ubuntu/gpg
                     state: present

           - name: Add Docker Repository
             apt_repository:
                     repo: deb https://download.docker.com/linux/ubuntu focal stable
                     state: present

           - name: Update apt and install Docker CE
             apt: update_cache=yes name=docker-ce state=latest

           - name: Install Docker Module for Python
             pip:
                     name: docker
           - name: Pull default docker image
             docker_image:
                     name: "{{ default_container_image }}"
                     source: pull
           - name: Create container
             docker_container:
                     name: "{{ default_container_name }}{{ item }}"
                     image: "{{ default_container_image }}"
                     state: started
                     ports: "8080:80"
             with_sequence: count={{ create_containers }}

Go ahead and confirm if Docker is actually running using the below ad-hoc command:

$ ansible all -m shell -a 'systemctl status docker'
192.168.50.3 | CHANGED | rc=0 >>
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2020-11-06 17:17:42 EAT; 17h ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 16327 (dockerd)
      Tasks: 11
     Memory: 22.0M
     CGroup: /system.slice/docker.service
             └─16327 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
192.168.50.3 | CHANGED | rc=0 >>
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2020-11-06 17:17:52 EAT; 17h ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 15750 (dockerd)
      Tasks: 13
     Memory: 209.1M
     CGroup: /system.slice/docker.service
             └─15750 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Confirm the pulled images on the remote servers with the below Ansible Ad-hoc command:

$ ansible all -m shell -a 'docker images'           
192.168.50.3 | CHANGED | rc=0 >> 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE 
nginx               latest              c39a868aad02        28 hours ago        133MB 
192.168.50.4 | CHANGED | rc=0 >> 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE 
nginx               latest              c39a868aad02        28 hours ago        133MB

Confirm running containers as well.

$ ansible all -m shell -a 'docker ps'               
192.168.50.3 | CHANGED | rc=0 >>
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
dde76d45b0c7        nginx               "/docker-entrypoint.…"   26 seconds ago      Up 23 seconds       0.0.0.0:8080->80/tcp   nginx1
192.168.50.4 | CHANGED | rc=0 >>
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
c7b6e5381ed8        nginx               "/docker-entrypoint.…"   26 seconds ago      Up 24 seconds       0.0.0.0:8080->80/tcp   nginx1

You can use various Ad-hoc commands to manage containers in the individual remote nodes from the Ansible node. Examples below:

Let us open port 8080 on our remote nodes:

$ ansible all -m shell -a 'ufw allow 8080/tcp'
192.168.50.3 | CHANGED | rc=0 >>
Rule added
Rule added (v6)
192.168.50.4 | CHANGED | rc=0 >>
Rule added
Rule added (v6)

Now navigate to your browser, enter ‘http://<your-remote-host-ip>:8080. You should get Nginx welcome page from both of your remote servers.

List the IDs of all running containers:

$ ansible all -m shell -a '(docker ps -aq)'
192.168.50.3 | CHANGED | rc=0 >>
3e182d1f3a42
192.168.50.4 | CHANGED | rc=0 >>
0e6e05f18ec8

To stop all running containers:

$  ansible all -m shell -a 'docker stop $(docker ps -aq)'
192.168.50.3 | CHANGED | rc=0 >>
3e182d1f3a42
192.168.50.4 | CHANGED | rc=0 >>
0e6e05f18ec8

Delete all running containers in all nodes:

$ ansible all -m shell -a 'docker rm $(docker ps -aq)'
192.168.50.3 | CHANGED | rc=0 >>
3e182d1f3a42
192.168.50.3 | CHANGED | rc=0 >>
0e6e05f18ec8

This has been a step-by-step guide on how to manage Docker Containers with Ansible. Ansible is a very crucial tool for IT Engineers which helps in managing many remote servers from a centralized server. It is a tool you would want to learn about ease your IT operations. I hope our guide has been informative to you. Below are even more interesting guides for you:

LEAVE A REPLY

Please enter your comment!
Please enter your name here

13 − 9 =