This is a tutorial post for my own notes, in this post we will walk through the steps to install docker on two ubuntu servers using ansible.
DISCLAIMER: This is my first time using ansible, so if you are looking for best practices, look elsewhere.
Installing "ansible" on a mac
brew install ansible
NOTE: you will need homebrew installed - https://brew.sh/
Creating Inventory file
In order for ansible to execute in parallel on multiple hosts, it needs the hosts setup in inventory. For this walk through, you will need to spin up a few EC2 instances in aws and add them to your inventory file hosts
.
You can group these files in the inventory file like so:
[testservers]
ec2-XXX.us-west-1.compute.amazonaws.com ansible_user=ubuntu ansible_ssh_private_key_file=/path/to/key
ec2-XXX.us-west-1.compute.amazonaws.com ansible_user=ubuntu ansible_ssh_private_key_file=/path/to/key
In your terminal create a new folder docker-playbook
and create a new file in that folder called hosts
and add your servers ip addresses or dns names, along with the user and private key info.
Now that we have our inventory file setup, we can test our connectivity:
ansible all -i hosts -m ping
This command will connect to each server and run a ping program and should result with some output like the following:
ec2-xxxxx.us-west-1.compute.amazonaws.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
ec2-xxxxxx.us-west-1.compute.amazonaws.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
๐ Congrats! ๐ You have successfully connected to your servers using ansible!
To run for our specific inventory group, we replace all with the name of our group.
ansible testservers -i hosts -m ping
Creating a playbook
Now that we have ansible installed and able to connect to our hosts, we need to create a playbook.
In a working directory, create a new file called playbook.yml
, open the file in an editor. This is where we will place all of our tasks to be applied to our hosts.
A task is a yaml object with specific properties that instruct ansible to perform instructions on the host machines in parallel.
In order to install docker we would normally run the following instructions on the command-line of a host machine:
apt update -y
sudo apt update -y
sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io -y
With ansible, we will create a playbook that can safely execute the same functionality as above using a list of tasks defined in the playbook yml file.
playbook.yml
The first thing we do is apply the three dashes `---` then use comments to give the file a title.
---
# Install docker on ubuntu
- hosts: testservers
become: true
Next in the playbook, we specify the hosts we would like to target in the hosts file and that we want to run this playbook as root
user, using the become
statement.
Next we add a list of tasks:
...
tasks:
- name: Install aptitude using apt
apt: name=aptitude state=latest update_cache=yes force_apt_get=yes
The first tasks installs aptitude, because anisble
is setup to use aptitude for scripts.
- name: Install required system packages
apt: name={{ item }} state=latest update_cache=yes
loop: ['apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common']
This task is similar to the first using the apt property, but it also contains a variable handler in the apt statement. {{ item }}
this item variable is set by the loop property, which will iterate through each item in the list and execute the apt command. This will install the following packages: apt-transport-https, ca-certificates, curl and software-properties-common.
- name: Add Docker GPG apt key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
In this task, we install the gpg key for docker, using the apt_key
command. Which takes a url, and state. The state setting is present, which means, if it already exists, keep it.
- name: Add Docker Repository
apt_repository:
repo: deb https://download.docker.com/linux/ubuntu focal stable
state: present
In this task, we add the docker repository to the apt get sources.list.
- name: Update apt and install docker-ce, docker-ce-cli, containerd.io
apt: update_cache=yes name={{ item }} state=latest
loop: ['docker-ce', 'docker-ce-cli', 'containerd.io']
This tasks installs docker using apt.
Run an ansible playbook
Lets run this playbook against our hosts:
ansible-playbook -i hosts playbook.yml
๐ Awesome! ๐ You have created an ansible playbook to install docker on an ubuntu 20 system.
- name: Install Python
apt: name={{ item }} state=latest update_cache=yes
loop: ['python3-pip', 'virtualenv', 'python3-setuptools']
- name: Install Docker Module for Python
pip:
name: docker
Pulling a docker image
In order to use docker with ansible, we need to install the python SDK
Now we add the task to pull the image
- name: Pull image
docker_image:
name: "nginx"
source: pull
Running a container
- name: create container
docker_container:
container_default_behavior: compatibility
name: "nginx"
image: "nginx"
ports:
- "8080:80"
state: 'started'
restart_policy: 'always'
Documentation: https://docs.ansible.com/ansible/2.5/modules/docker_container_module.html
Summary
There is a lot to learn about ansible, but the documentation is solid and easy to search for, also there are plenty of examples and cheatsheets published, here is one:
Here is the full playbook.yml
---
- hosts: all
become: true
tasks:
- name: Install aptitude using apt
apt: name=aptitude state=latest update_cache=yes force_apt_get=yes
- name: Install required system packages
apt: name={{ item }} state=latest update_cache=yes
loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common' ]
- 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 Python
apt: name={{ item }} state=latest update_cache=yes
loop: ['python3-pip', 'virtualenv', 'python3-setuptools']
- name: Install Docker Module for Python
pip:
name: docker
- name: Pull image
docker_image:
name: "nginx"
source: pull
- name: Create container
docker_container:
container_default_behavior: compatibility
name: "nginx"
image: "nginx"
ports:
- "8080:80"
state: 'started'
restart_policy: 'always'