Automating Docker Installation on Ubuntu with Ansible
Introduction Automating server processes has become a crucial part of systems administration due to the ephemeral nature of contemporary application environments. Tools like Ans...
By Software Development Team
Introduction
Automating server processes has become a crucial part of systems administration due to the ephemeral nature of contemporary application environments. Tools like Ansible streamline server setup automation with standardized procedures, minimizing errors from manual configuration. Ansible's simple architecture doesn't require special software on nodes and includes robust features and modules for scripting automation.
This guide details using Ansible to automate Docker installation on Ubuntu, building on the steps outlined in the guide for installing and using Docker. Docker simplifies managing containers, offering resource-isolated environments that are more portable and efficient than virtual machines.
Note: This guide was verified on Ubuntu 24.04 LTS. It may work on other Ubuntu versions with some adjustments, particularly in repository configuration.
Key Takeaways:
- Idempotency: Safely re-run playbooks multiple times without unwanted changes, as each task checks system state before acting.
- Modern GPG Key Management: Stores repository keys in
/etc/apt/keyrings, replacing deprecated methods. - Docker Compose v2: Integrated as a plugin, providing
docker composesubcommands. - Automatic Ubuntu Codename Detection: The
{{ ansible_distribution_release }}variable ensures compatibility across versions. - Community Docker Collection: Must be installed on the control node with
ansible-galaxy collection install community.docker. - Comprehensive Docker Setup: Requires core packages like
docker-ce,docker-ce-cli,containerd.io, and others. - Group Membership: Changes require logout and login to take effect.
- Task Sequencing: Crucial as Ansible executes tasks synchronously, dependencies must be installed first.
- Verbose Mode (
-vvv): Provides detailed debugging info for network and permission issues. - Playbook Advantages: Offers better repeatability than shell scripts with built-in idempotency and version control.

Prerequisites
To execute the automated setup, you'll need:
- Ansible Control Node: An Ubuntu 24.04 machine with Ansible installed, configured to connect to hosts via SSH keys. The control node should have a user with sudo permissions and an enabled firewall.
- Ansible Hosts: One or more remote Ubuntu 24.04 servers, prepped as per initial server setup guides.
Note: Ensure the control node can connect and execute commands on hosts. Test connections as outlined in Ansible setup guides.
What Does This Playbook Do?
This playbook automates the process of installing Docker on Ubuntu, allowing repeated use for installations. It performs these actions on Ansible hosts:
- Install
aptitude, preferred by Ansible overapt. - Install required system packages.
- Configure the Docker GPG key using modern keyring methods.
- Add the Docker repository to
aptsources. - Install Docker.
- Install Docker Compose (v2 plugin).
- Install the Python Docker module via
pip. - Pull a default image from Docker Hub.
- Create containers as specified by variables, executing defined commands.
Once completed, containers will be created based on your configuration.
Preparing Your Playbook
Create a playbook.yml file, which defines your tasks:
---
- hosts: all
become: true
vars:
container_count: 4
default_container_name: docker
default_container_image: ubuntu
default_container_command: sleep 1d
These declarations set the target servers and specify root privileges. Variables store data for easy future updates.
Adding Package Installation Tasks
Ansible executes tasks synchronously, ensuring each finishes before the next begins. Tasks are idempotent, only acting if necessary.
Add tasks to install aptitude and required packages:
tasks:
- name: Install aptitude
apt:
name: aptitude
state: latest
update_cache: true
- name: Install required system packages
apt:
pkg:
- ca-certificates
- curl
- gnupg
- software-properties-common
- python3-pip
- python3-venv
- python3-setuptools
state: latest
update_cache: true
These tasks ensure the presence and update of packages using Ansible's apt module.
Adding Docker Installation Tasks
The task installs Docker from the official repository, adding the GPG key and repository, then installing Docker and related plugins:
- name: Create keyrings directory
file:
path: /etc/apt/keyrings
state: directory
mode: '0755'
- name: Download Docker GPG key
get_url:
url: https://download.docker.com/linux/ubuntu/gpg
dest: /etc/apt/keyrings/docker.asc
mode: '0644'
force: true
- name: De-armor Docker GPG key for APT
command: gpg --dearmor --yes --output /etc/apt/keyrings/docker.gpg /etc/apt/keyrings/docker.asc
args:
creates: /etc/apt/keyrings/docker.gpg
- name: Add Docker repository
apt_repository:
repo: "deb [signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
filename: docker
- name: Update apt and install Docker Engine
apt:
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
state: latest
update_cache: true
- name: Install Docker Module for Python
pip:
name: docker
This uses modern methods for keyring management and installs Docker Compose as a plugin.
Adding Docker Image and Container Tasks
Ensure the community.docker collection is installed before adding tasks for Docker images and containers:
- name: Pull default Docker image
community.docker.docker_image:
name: "{{ default_container_image }}"
source: pull
- name: Create default containers
community.docker.docker_container:
name: "{{ default_container_name }}{{ item }}"
image: "{{ default_container_image }}"
command: "{{ default_container_command }}"
state: present
with_sequence: count={{ container_count }}
These tasks pull Docker images and create containers based on specified variables.
Reviewing Your Complete Playbook
The final playbook should look like this:
---
- hosts: all
become: true
vars:
container_count: 4
default_container_name: docker
default_container_image: ubuntu
default_container_command: sleep 1d
tasks:
- name: Install aptitude
apt:
name: aptitude
state: latest
update_cache: true
- name: Install required system packages
apt:
pkg:
- ca-certificates
- curl
- gnupg
- software-properties-common
- python3-pip
- python3-venv
- python3-setuptools
state: latest
update_cache: true
- name: Create keyrings directory
file:
path: /etc/apt/keyrings
state: directory
mode: '0755'
- name: Download Docker GPG key
get_url:
url: https://download.docker.com/linux/ubuntu/gpg
dest: /etc/apt/keyrings/docker.asc
mode: '0644'
force: true
- name: De-armor Docker GPG key for APT
command: gpg --dearmor --yes --output /etc/apt/keyrings/docker.gpg /etc/apt/keyrings/docker.asc
args:
creates: /etc/apt/keyrings/docker.gpg
- name: Add Docker repository
apt_repository:
repo: "deb [signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
filename: docker
- name: Update apt and install Docker Engine
apt:
pkg:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
state: latest
update_cache: true
- name: Install Docker Module for Python
pip:
name: docker
- name: Pull default Docker image
community.docker.docker_image:
name: "{{ default_container_image }}"
source: pull
- name: Create default containers
community.docker.docker_container:
name: "{{ default_container_name }}{{ item }}"
image: "{{ default_container_image }}"
command: "{{ default_container_command }}"
state: present
with_sequence: count={{ container_count }}
This playbook can be tailored to fit specific needs and workflows. Ensure proper indentation as YAML syntax is sensitive to it.
Running Your Playbook
Run the playbook on designated servers. For instance, to execute on server1 as sammy:
ansible-playbook playbook.yml -l server1 -u sammy
Check the output to ensure successful execution with no failures. Log into the server to verify container creation:
ssh sammy@your_remote_server_ip
sudo docker ps -a
You should see a list of created containers, confirming the playbook execution.
Troubleshooting Common Errors
- GPG Key Errors: Verify URL reachability and network settings if GPG keys fail to download.
- Repository Issues: Check APT sources and ensure the correct repository is added.
- Package Failures: Use
sudo apt --fix-broken installto resolve package conflicts. - Permission Denied: Add users to the
dockergroup for Docker command access withoutsudo. - Service Not Starting: Check Docker service status and logs to diagnose issues.
- Python Module Issues: Ensure
pipand Python are properly configured and updated. - Connection Failures: Confirm SSH connectivity and correct inventory configuration.

FAQs
- Required Ansible Version: Ansible 2.10+ is recommended for compatibility with the
community.dockercollection. - Docker Compose Version: Installs Docker Compose v2, used as a Docker subcommand.
- Why Use Ansible?: Provides repeatability and auditability, with idempotent tasks for consistent states.
- Idempotent Meaning: Ensures predictable results on repeated runs by checking system states.
- Multiple Server Provisioning: Use inventory groups for simultaneous provisioning.
- Custom Playbook vs. Galaxy Role: A custom playbook offers transparency, while Galaxy roles provide convenience.
- Verify Docker Installation: Check Docker version and run test containers to confirm successful installation.

Conclusion
Automating infrastructure setup saves time and ensures consistent server configurations. This guide demonstrated using Ansible to automate Docker installation on Ubuntu servers, including modern Compose support. Explore official Ansible documentation for more customization options with the docker_container module.
Further Reading
Explore more Ansible tutorials:
- Install and Configure Ansible on Ubuntu: Guide
- Using Ansible Roles for Infrastructure
- Writing Ansible Playbooks