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"
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
This is the output of the succesful playbook run.
Excellent! And on the remote servers we can see results:
Server 1 - docker container status
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
Once .yaml is finished, save it and it’s ready to use playbook to ship it.
ansible-playbook -i inventory.yaml deploy-portainer.yml
Deployment went smooth and we can see results on our remote servers.
Server 1
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.