How To Manage Docker Containers With Ansible

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

Step 1: Install Ansible on your system

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.

Ubuntu / Debian

To install Ansible on Ubuntu/Debian, please run the below command:

sudo apt update && sudo apt install ansible -y

CentOS / Rocky Linux / AlmaLinux

Run the commands below

sudo yum install epel-release
sudo yum install ansible

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

$ ansible --version
ansible [core 2.16.3]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.12.3 (main, Sep 11 2024, 14:17:37) [GCC 13.2.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

Step 2: 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 user@remote-server-ip

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:

[myservers]
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" 
}

Step 3: Install Docker CE on Linux

Since we need Docker for deploying containers, we are going to install Docker CE on our remote servers.

Refer to the guide in the link below:

Step 4: 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:

$ vim create_docker_containers.yaml
---
- hosts: myservers
  become: true
  vars:
    create_containers: 1
    default_container_name: nginx
    default_container_image: nginx
          
  tasks:
    - 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 }}

Run the playbook:

$ ansible-playbook create_docker_containers.yaml --become --user=USER --become-user=root --become-method=sudo 

Where USER is replaced with the remote system user:

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 Thu 2024-11-07 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 Thu 2024-11-07 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.

Explore More with CloudSpinx

Looking to streamline your tech stack? Here at CloudSpinx, we deliver robust solutions tailored to your needs.

Your IT Journey Starts Here!

Ready to level up your IT skills? Our new eLearning platform is coming soon to help you master the latest technologies.

Be the first to know when we launch! Join our waitlist now.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Leave a Comment

Your email address will not be published. Required fields are marked *

Related Post

In this article we describe the process of configuring Containerd client to connect to a Sonatype Nexus container registry proxy/mirror. […]

For most system admins, their day-to-day life activities revolve around having access to remote systems.VNC an acronym for Virtual Network […]

PostgreSQL is an open-source object-relational database management system (ORDBMS) based on POSTGRES, Version 4.2. Postgresql was developed at the University […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.