Overview

Hello there fellow Linux adventurers. I hope you’re ready for today’s adventure in the land of automation. Through this article you’ll be shown steps how to deploy Docker container using Ansible on a remote Linux machine that runs Docker engine. By the end of article you should have enough understanding how to automate process of Docker container deployment on a multiple Linux inventory, with preset of environment variables and configs for needed Docker container.

Prerequisites

To successfully deploy Docker container on a remote Linux machine, there are following prerequisites that must be met before venturing forth and those are:

  • Python installed on your running workstation and on the remote Linux server,
  • Python Docker module for Ansible installed on your local workstation,
  • Ansible installed on your local workstation,
    • SSH access enabled with login parameters preset in Ansible inventory file
  • Docker engine installed and running on control node and managed nodes (Docker can be installed using Ansible or running the official Docker install script).

Docker can be installed running the official Docker install script or using Ansible. We’ve already covered that topic in article Install Docker using Absible. Also, some methods and examples covered with Docker and Ansible:

Install Python Docker module for Ansible

Most Linux distros comes with Python3 preinstalled, but for others Python Docker module that Ansible needs most likely will be missing and you’ll have to install it. That module is actually Docker SDK which Python uses to work with Docker. To avoid being interrupted amidst work, it’s better to install it and easiest way to do it is with “pip” tool:

Debian/Ubuntu
sudo apt install python3-pip

Fedora
sudo dnf install python3-pip

CentOS/RedHat
sudo yum python3-pip

Followed by installation of docker module:

pip3 install docker

If you by any chance encounter an error in Ansible that it cannot find the Python module, you’ll have to add a python interpreter variable in your inventory file. It’s located either in "/usr/bin/python3" or "/usr/lib/python3". Interpreter variable in the inventory file looks something like this:

ansible_python_interpreter=/usr/bin/python3

Write down the hosts in inventory file with the login parameters

For Ansible to do a successful job, first you have to add necessary parameters of the target machines in it’s inventory file. Usually, what is one of methods handling the inventor file is to create some folder and inside of it create inventory file. Just be careful what extension you give to your inventory file, because of difference between .yaml and .yml styles(Ansible supports both), but for this example we will use inventory in yaml format. After you create inventory file, open it with your favorite editor and enter parameters. Your inventory file should look something like this:

myhosts:
  hosts:
    192.168.124.203:
    192.168.124.122:
  vars:
    ansible_user: markon
    ansible_password: "markon1234"
    ansible_become_password: "markon1234"
    ansible_python_interpreter: /usr/bin/python3

Ansible playbook for Docker container deployment

While your inventory file is here to guide Ansible to “who” you want something to apply (meaning for which workststaions, VMs, network devices,…), your Ansible playbook .yml file is to guide Ansible “what” you want to be done. For testing purposes I’ve created file deploy-containers-playbook.yaml and filled with what actions I want to be done.

- hosts: myhosts
  become: true
  tasks:
    - name: pull the nginx docker image
      docker_image:
        name: nginx
        source: pull

    - name: deploy nginx docker container
      docker_container:
        name: nginx
        image: nginx
        state: started
        auto_remove: true
        ports:
          - "8080:80"

deploy docker container using ansible

Quick breakdown of playbook file:

  • “hosts: myhosts” - “hosts” is the block where we to define the targets(target machines, in our case remote servers), while “myhosts” are how I named my server group (your may vary and change it accordingly). Playbook will target only managed nodes you specified in inventory file.
  • “become: true” - Simply a flag to run the playbook with elevated privileges(sudo) in order to execute tasks succesfully.
  • “tasks” - Opening a list of tasks you want to be done. Pretty much self explainatory.
  • "- name: pull the nginx docker image" - Name of task to be done. Make it as descriptive as you can.
  • “docker_image:” - Invoking Docker command that manages docker image.
  • “name: nginx” - Specifying a name of Docker image you want to pull from Docker hub.
  • “source: pull” - Links to the remote repository and explains the needed task.
  • “name: deploy nginx Docker container” - Another descriptive name for a task you need to be done.
  • “docker_container:” - Another Docker command that manages Docker containers.
  • “name: nginx” - Name of Docker image that was pulled from Docker hub.
  • “image: nginx:stable” - Version of image that you’re pulling from Docker hub.
  • “state: started” - Environment variable that specifies that it needs to be started right after the deployment.
  • “auto_remove: true” - Environment variable that specifies that container will be removed automatically right after it stops.
  • “ports: “8080:80"” - Port mapping.

Ok so it’s time to run the playbook. This is the command syntax we’re going to execute:

ansible-playbook -i inventory.yaml deploy-containers-playbook.yml

deploy docker containe using ansible

deploy docker container using ansible

This is the output of the succesful playbook run.

Excellent! And on the remote servers we can see results:

deploy docker container using ansible

Server 1 - docker container status

deploy docker container using ansible

Server 2 - docker container status

Server 1

Server 2

Deploy containers with persistent volumes using Ansible

In another example we’ll show how to deploy Docker container with data persistance. we’ll use Portainer in this example. So first step is to create another .yml file, we’ll name it deploy-portainer.yaml, we’ll fill it in a similar fashion like previous one so it should look somewhat like this:

- hosts: myhosts
  become: true
  tasks:
    - name: Deploy Portainer
      docker_container:
        name: portainer
        image: portainer/portainer-ce
        ports:
          - "9000:9000"
          - "8000:8000"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - portainer_data:/data
        restart_policy: always

deploy docker containe with ansible

Once .yaml is finished, save it and it’s ready to use playbook to ship it.

ansible-playbook -i inventory.yaml deploy-portainer.yml

deploy docker container with ansible

Deployment went smooth and we can see results on our remote servers.

deploy docker container with ansible

Server 1

deploy docker container with ansible

Server 2

If you noticed how format and syntax writing for deploying Docker containers with Ansible are same as writing Docker compose files to deploy containers, well the reason is they both use .yaml format and the module is using the same syntax as Docker.

Summary

In this post we have went through the procedure of how to deploy Docker container using Ansible to a remote Linux machine, which consists of following steps:

  • Create inventory (inventory) file with information about managed nodes (remote Linux machines).
  • Wrote Ansible playbook for Docker container deployment and specified which container to download and run.
  • Successful playbook run and, as result, deployed Docker containers on managed nodes.

Thanks for your spared time. Practice your newly acquired skills and expand your knowledge base. Until next time, stay sharp.