Using Ansible to automate Docker installation on Ubuntu servers, ensuring consistency and efficiency.

Master Ansible Automation: Install Docker on Ubuntu 18.04

Introduction

To automate Docker installation on Ubuntu 18.04, Ansible offers a streamlined approach that saves time and reduces human error. By using an Ansible playbook, you can efficiently set up Docker on remote servers, ensuring consistency across multiple machines. This guide walks you through the steps of creating and running an Ansible playbook, from installing necessary packages to pulling Docker images and creating containers. Whether you’re managing a small fleet of servers or scaling up, automating Docker setup with Ansible makes server management smoother and more reliable.

What is Ansible?

Ansible is a tool used to automate server setup and management. It helps by performing tasks like installing software, configuring systems, and setting up environments across multiple servers without needing manual intervention. The main benefit is that it reduces errors and saves time by ensuring all servers are set up in a standardized and automated way.

Step 1 — Preparing your Playbook

Alright, let’s get straight into the core of the automation process—the playbook.yml file. Think of it as the brain of your automation setup in Ansible, where all your tasks are defined. Each task is like a small action that Ansible will perform, such as installing a package or setting up system configurations. The real magic of Ansible happens when these tasks are automated and executed across all your servers, making sure everything runs smoothly and stays consistent.

Now, before you can start adding tasks to your playbook, you need to create the file. Don’t stress, it’s easy! Just open your terminal and type this command to get started:

$ nano playbook.yml

This will open up an empty YAML file in the nano text editor. From here, you’ll set up the basics of your playbook. Here’s what a simple structure might look like to get things rolling:


hosts: all
become: true
vars:
  container_count: 4
  default_container_name: docker
  default_container_image: ubuntu
  default_container_command: sleep 1

What’s going on in this block?

  • hosts: This line tells Ansible which servers to target. When you use all , it means the playbook will apply to every server in your inventory. If you want to focus on specific servers, you can change that.
  • become: This part is really important. It ensures that every command Ansible runs has root privileges. Without this, tasks that need admin rights—like installing software or adjusting system settings—could fail. It’s essential to avoid running into issues later on.
  • vars: This is where you define variables for your playbook. Think of these as placeholders that make the playbook flexible. You can change these values anytime, and the playbook will adjust accordingly, which makes it easy to reuse for different projects. Here’s what each variable means:
  • container_count: This tells Ansible how many containers to create. By default, it’s set to 4, but you can easily change it to create as many containers as you need.
  • default_container_name: This sets the base name for your containers. You can call them anything you like, such as docker1, docker2, etc. It helps you keep things organized.
  • default_container_image: This specifies the Docker image to use for creating containers. Right now, it’s set to ubuntu, but you can swap it out for any image you want.
  • default_container_command: This defines the default command to run in the containers. In the example above, it’s set to sleep 1 , which means each container will sleep for 1 second after it’s created. You can change this to any other command you need.

YAML files can be a bit picky about indentation, so be careful! Every space counts, and even one small mistake can cause Ansible to throw an error. Generally, stick to two spaces for each level of indentation to stay on the safe side. It’s a good idea to double-check your formatting before moving on to the next step.

Once you’ve added your variables and set up the basics, just save the file. You’re all set! If you’re curious about what the finished playbook looks like, you can jump ahead to Step 5. But for now, focus on getting this initial structure right. After that, you’ll be ready to add more tasks and build out the rest of your automation setup!

Ansible Automation Essentials

Step 2 — Adding Packages Installation Tasks to your Playbook

Alright, let’s jump into adding some important packages to your playbook. Ansible is pretty clever when it comes to executing tasks—it runs them in the order you list them in your playbook. This might seem obvious, but it’s actually really important. Think about it like making a sandwich: you can’t put the cheese on the bread until the bread is actually out of the bag, right? Ansible makes sure that one task finishes before the next one starts, so things run smoothly without any hiccups. This step-by-step approach is also what helps keep everything running efficiently when you’re managing server configurations. Plus, it’s one of the reasons Ansible is so powerful—tasks are independent and reusable, meaning you can use them in other playbooks in the future, saving you time and effort.

So here’s the plan: we’re going to add some tasks to install a few key system packages on your servers. First, we need aptitude , which is a package manager that Ansible uses to install and manage packages on your server. Ansible tends to prefer aptitude because it handles package dependencies better than other managers. Once aptitude is set up, we’ll install a few other important packages that are needed for Docker and related setups.

Here’s how it looks in your playbook.yml file:


tasks:
  – name: Install aptitude
    apt:
      name: aptitude
      state: latest
      update_cache: true
  – name: Install required system packages
    apt:
      pkg:
        – apt-transport-https
        – ca-certificates
        – curl
        – software-properties-common
        – python3-pip
        – virtualenv
        – python3-setuptools
      state: latest
      update_cache: true

Explanation of Each Task:

Install aptitude: This task uses the apt module in Ansible to install the aptitude package. By setting state: latest , we make sure you’re installing the newest version available. The update_cache: true part ensures that the package cache is updated before starting the installation, so Ansible grabs the freshest version.

Install required system packages: This task installs a series of system packages that are essential for Docker to run properly. The list of packages is specified under the pkg key. Let’s break down what each one does:

  • apt-transport-https: This package allows apt to fetch packages from HTTPS repositories, which is super important for secure communication when downloading from trusted sources.
  • ca-certificates: This ensures your server can recognize SSL certificates. It’s necessary for securely connecting to repositories and downloading packages over HTTPS.
  • curl: A handy command-line tool used to transfer data. It’s often used to download resources like Docker installation scripts from the internet.
  • software-properties-common: This utility helps manage software repositories, making sure your system can handle the sources it needs for Docker.
  • python3-pip: This is the Python package manager, which helps install additional Python modules that might be needed for applications, including those related to Docker.
  • virtualenv: A tool for creating isolated Python environments. This is great for ensuring that Python apps, like Docker, don’t step on each other’s toes.
  • python3-setuptools: This package helps with packaging Python projects, making sure everything runs smoothly—especially when dealing with Python dependencies that Docker might need.

Now, here’s the best part: Ansible is smart enough to fall back to apt if aptitude isn’t available. This flexibility means the required packages are always installed, no matter what. By setting state: latest , you’re ensuring that the most up-to-date versions are installed. This means you’ll always get the latest features and security updates.

The outcome? Your system won’t just install the packages; it will keep them updated too. Thanks to the apt module, everything stays up to date, which helps minimize the risk of vulnerabilities caused by outdated versions. If you find that you need different packages or extras, feel free to adjust the list to fit your specific needs.

With these tasks added, you’re all set to ensure your server is ready to go with Docker and any other dependencies you might need. The best part? This setup can be reused in other playbooks, making your workflow more efficient and streamlined.

Note: You can always modify this playbook as needed for additional packages or specific configurations that fit your environment.

What is Ansible?

Step 3 — Adding Docker Installation Tasks to your Playbook

Now comes the fun part—getting Docker up and running on your server! In this step, we’ll add the tasks to your playbook.yml file to make sure that Docker gets installed smoothly and automatically, right from the official Docker repository. But before we dive into the installation, there are a few important steps to make sure everything is set up properly.

First, we need to add the Docker GPG key. Think of this key like a seal of approval. It confirms that the Docker packages you’re about to install are legit and coming from the official source. Without this key, you could end up downloading something sketchy—definitely not what you want when dealing with system configurations, right?

Next, you’ll add the Docker repository to your system’s list of sources. This step ensures that you can download Docker directly from the trusted Docker package repository, giving you access to the latest and most secure version.

Once that’s all set, the next step is installing Docker itself, followed by the Docker Python module. This Python module is super important if you plan on interacting with Docker using Python scripts, enabling you to automate Docker tasks in the future.

Now, let’s get into the details of how you can set this all up in your playbook:


tasks:
  – 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 bionic stable
      state: present
  – name: Update apt and install docker-ce
    apt:
      name: docker-ce
      state: latest
      update_cache: true
  – name: Install Docker Module for Python
    pip:
      name: docker

Breaking It Down:

  • Add Docker GPG apt Key: This task uses the apt_key module to download and add the GPG key for the Docker repository to your system. By doing this, you ensure that the packages you install come from the official Docker source. It’s a simple but important step to keep things secure and avoid installing anything suspicious.
  • Add Docker Repository: Here, the apt_repository module is used to tell your system where to find Docker packages by adding Docker’s official repository to your list of sources. The URL points to Docker’s official repository for Ubuntu 18.04 (Bionic), making sure you get the right version for your system. You’ll always get the latest stable release of Docker this way.
  • Update apt and install docker-ce: Now, the apt module takes over to install Docker Community Edition ( docker-ce ) directly from the repository you just added. The state: latest part ensures that you’re getting the latest version of Docker available, and update_cache: true refreshes the local package list, making sure you’re installing the most up-to-date version.
  • Install Docker Module for Python: Lastly, this task installs the Docker Python module using pip , which is Python’s package manager. This is essential if you want to interact with Docker using Python scripts. It lets you automate tasks like managing containers, pulling images, and more. If you’re planning to integrate Docker with any Python-based automation tools, this is a must-have.

Each of these tasks is super important for ensuring that Docker gets installed correctly and is ready to go on your server. Plus, they simplify the whole installation process, saving you time and effort. The best part about using Ansible is that you can easily reuse these tasks in other playbooks or on different servers, so your setup is always consistent, automated, and error-free.

By using Ansible’s modules like apt_key , apt_repository , apt , and pip , you eliminate the need for manually configuring everything. This not only makes the setup more reliable, but also helps you scale your infrastructure easily as you add more servers or containers. It’s a smooth, repeatable process that makes managing Docker a breeze.

Docker Installation on Ubuntu

Step 4 — Adding Docker Image and Container Tasks to your Playbook

Alright, now that we’ve got everything set up, let’s dive into Docker. In this step, you’ll be adding tasks to your playbook.yml that will pull the Docker image and create the containers. Think of this step like laying the foundation before building the rest of your house—super important to get everything solid before moving on.

First, we need to pull the Docker image. This image is like the blueprint for your container, and it usually comes from Docker Hub, the official home for all Docker images. The best part about Docker Hub is that it’s well-organized and trusted, so you know you’re getting a solid foundation to build your containers on. Once the image is pulled, the next step is to create the containers based on the settings you’ve already put in your playbook. This guarantees that your containers will be set up just the way you want them.

Let’s take a closer look at how to add this to your playbook.yml file:


tasks:
  – name: Pull default Docker image
    docker_image:
      name: “{{ default_container_image }}”
      source: pull
  – name: Create default containers
    docker_container:
      name: “{{ default_container_name }}{{ item }}”
      image: “{{ default_container_image }}”
      command: “{{ default_container_command }}”
      state: present
    with_sequence:
      count={{ container_count }}

Explanation of Each Task:

Pull default Docker image: This is the first task. The docker_image module pulls the Docker image you defined earlier in the playbook, using the default_container_image variable. The source: pull command tells Ansible to grab the image from Docker Hub, ensuring you’re using the latest version. This image will serve as the base for all your containers, keeping everything consistent.

Create default containers: Here comes the fun part—the docker_container module takes care of actually creating the containers. This task does a few things:

  • name: This is where we get a little clever. The name of each container is created using the default_container_name variable, plus item from the with_sequence loop. This means that if you want 4 containers, Ansible will create containers named docker1, docker2, docker3, and docker4. You can easily adjust how many containers you want by changing the container_count variable.
  • image: This tells Ansible which Docker image to use for the containers. It pulls the default_container_image you set earlier, so all the containers are based on the same image. This ensures uniformity across them all.
  • command: This part tells Ansible what to do inside each container once it’s created. The default_container_command variable stores the command to run. In this case, it’s set to sleep 1d , meaning each container will “sleep” for a full day after it’s created. You can change this to any command you want, like starting a service or running an app.
  • state: Setting state: present makes sure that the containers aren’t just created but also running on your server. It ensures they’re up and active, ready for use.
  • with_sequence: Here’s the neat trick. with_sequence generates a sequence of numbers based on the container_count variable. For example, if container_count is set to 4, Ansible will loop and create 4 containers. The item variable represents the current loop iteration (1, 2, 3, etc.), which is used to give each container a unique name—docker1, docker2, and so on. This loop saves you from having to manually define each container, making the process quicker and ensuring everything is set up the same way. It’s especially useful when you need to create a lot of containers. And because the same Docker image and command are used for all containers, you’re keeping everything consistent, which is key for building scalable and stable environments.

By using Ansible’s modules like docker_image and docker_container , you can automate the entire Docker container creation process. No more manually configuring each container or worrying about mistakes or typos. Everything runs automatically, saving you time and reducing the chance of human error. And the best part? This process is repeatable and reusable, so you can use it in future playbooks or across other servers, making your life as an admin a whole lot easier.

Ensure that the playbook is correctly formatted to avoid syntax errors when running Ansible tasks.


What is Docker?

Step 5 — Reviewing your Complete Playbook

So, here we are. You’ve made it this far, and now it’s time to review your masterpiece—your playbook.yml file. If everything went according to plan, this is what your playbook should look like, though you might notice a few small changes depending on how you customized it for your needs. Here’s an example setup that outlines the basic structure, with specific values set for variables like how many containers you want and the Docker image you’ll use:


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:
        – apt-transport-https
        – ca-certificates
        – curl
        – software-properties-common
        – python3-pip
        – virtualenv
        – python3-setuptools
      state: latest
      update_cache: true
  – 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 bionic stable
      state: present
  – name: Update apt and install docker-ce
    apt:
      name: docker-ce
      state: latest
      update_cache: true
  – name: Install Docker Module for Python
    pip:
      name: docker
  – name: Pull default Docker image
    docker_image:
      name: “{{ default_container_image }}”
      source: pull
  – name: Create default containers
    docker_container:
      name: “{{ default_container_name }}{{ item }}”
      image: “{{ default_container_image }}”
      command: “{{ default_container_command }}”
      state: present
    with_sequence: count={{ container_count }}

Let’s break it down a bit more:

  • hosts: The hosts: all part tells Ansible that the playbook will apply to every server in your inventory. It’s like sending a message to all the servers in the network, telling them, “Hey, we’re about to make some changes!”
  • become: become: true is Ansible’s way of saying, “Let’s do this with admin privileges!” This ensures that every task in the playbook has the necessary permissions to install software or change system settings.
  • vars: This section is where all the magic happens. Here’s where you define variables that will be used throughout your playbook. Think of it as setting the stage before the performance begins. You can change the variables later to adjust the configuration without rewriting the entire playbook.
  • container_count: This is the number of containers you want to create. Set it to whatever suits your needs—4, 10, 100, or more!
  • default_container_name: This is the base name for your containers. You can customize this too, but by default, it’s set to docker .
  • default_container_image: This tells Ansible which Docker image to use. Right now, it’s set to ubuntu , but you can swap it out for any Docker image you need.
  • default_container_command: This is the command your containers will run once created. In this case, it’s set to make each container sleep for a day, but you could have it run any command, like starting a service or running a program.

tasks: Now comes the part where things really happen. Each task represents a small action that Ansible will perform in sequence. Tasks are like the steps of a recipe: each one builds on the last until you’ve got your complete setup.

  • Installing aptitude and system packages: This ensures that your server has everything it needs to install Docker. Aptitude is like a smart package manager, and the other packages are tools Docker needs to run properly.
  • Adding the Docker GPG key: Here’s the safety check. This step ensures that the packages you’re about to install are from a trusted source (Docker’s official repository).
  • Adding the Docker repository: By adding Docker’s official repository to your system, you’re making sure that Ubuntu knows where to fetch the latest Docker packages from.
  • Installing Docker Community Edition: With everything set up, Ansible will go ahead and install the latest version of Docker. It’s like hitting the “download” button on Docker’s official page—only much faster and automated.
  • Installing the Docker Python module: This module will allow you to interact with Docker using Python scripts. So, if you need to automate Docker tasks programmatically, this step’s crucial.
  • Pulling the Docker image: Here, Ansible will fetch the Docker image you specified earlier (which, in this case, is ubuntu ), and that image will become the base for your containers.
  • Creating the Docker containers: Finally, Ansible creates the containers using the Docker image and command you’ve set up. And here’s the beauty of it: we use a loop to automatically create as many containers as you need—just set the container_count and let Ansible handle the rest. Each container gets a unique name, like docker1, docker2, etc.

Customizing the Playbook: Feel free to make this playbook your own! You could push your own Docker images to Docker Hub, or maybe you want to tweak the container settings, like adding networks or mounting volumes. This playbook is flexible enough to adapt to your specific needs, so don’t be afraid to experiment.

YAML files are picky about indentation. The structure of the file relies on spaces to organize everything. If your indentation is off, Ansible might throw an error. So, always make sure you’re using consistent two-space indentations. It’s a small thing, but it makes a big difference.

Once you’ve got everything configured the way you like it, just save the file and you’re ready to roll. The playbook is all set, and you’re now just a few commands away from automating your Docker setup across any number of servers. How cool is that?

Automating Docker with Ansible

Step 6 — Running your Playbook

You’ve done the hard part—set up your playbook, added your tasks, and now it’s time to run it on your server. This is when everything comes together. By default, Ansible playbooks are set to run on every server in your inventory. But in this case, you don’t need to run it on all servers, just the one you want to target. Let’s say you’re working with server1 and you want to run the playbook there. You can execute the following command:

$ ansible-playbook playbook.yml -l server1 -u sammy

Breaking Down the Command:

  • ansible-playbook playbook.yml : This part is straightforward. It tells Ansible to run the playbook you just created, named playbook.yml. It’s like telling Ansible, “Hey, it’s time to start running the show.”
  • -l server1 : The -l flag is how you specify which server you want to target. In this example, you’re focusing on server1, but you could swap it out with any other server in your inventory if needed.
  • -u sammy : The -u flag allows you to specify which user account Ansible should use to log into the remote server. So here, sammy is the username. Of course, if you’re using a different user, you’d replace it with the correct one.

Once you run this command, Ansible will spring into action, executing all the tasks you defined in your playbook on server1. You’ll see something like this in the terminal:

Output
changed: [server1] TASK [Create default containers] *****************************************************************************************************************
changed: [server1] => (item=1)
changed: [server1] => (item=2)
changed: [server1] => (item=3)
changed: [server1] => (item=4)
PLAY RECAP ***************************************************************************************************************************************
server1   : ok=9  changed=8  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

Understanding the Output:

  • changed: This line is your confirmation that something changed on server1. For example, it shows that the task to create containers has been successfully completed. If there were any changes, like container creation or configuration, this will tell you about them.
  • TASK [Create default containers] : This refers to the task where Ansible is creating the Docker containers. As you can see, the playbook will repeat this task multiple times, once for each container you want to create. In the output, it shows that docker1, docker2, docker3, and docker4 were created. This is the fun part when the containers are actually spun up!
  • PLAY RECAP : This section summarizes how the playbook ran. It tells you how many tasks were successful ( ok=9 ), how many changes were made ( changed=8 ), and whether there were any errors. In this case, everything went smoothly: no errors, no skipped tasks—just a perfect run.

Verifying the Containers:

After you run the playbook and see that the output shows no errors, it’s time to check if those containers actually got created. Here’s how you can verify:

  • SSH into the server: Log in to server1 using SSH with this command:
    $ ssh sammy@your_remote_server_ip
  • List the Docker containers: Once logged in, check if the containers were created by running:
    $ sudo docker ps -a

The output should look something like this:

Output
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
a3fe9bfb89cf        ubuntu              “sleep 1d”               5 minutes ago       Created                    –                    docker4
8799c16cde1e        ubuntu              “sleep 1d”               5 minutes ago       Created                    –                    docker3
ad0c2123b183        ubuntu              “sleep 1d”               5 minutes ago       Created                    –                    docker2
b9350916ffd8        ubuntu              “sleep 1d”               5 minutes ago       Created                    –                    docker1

Here, you can see that all your containers were created successfully, and they’re listed in the “Created” state. This is exactly what you should expect!

Wrapping It Up:

So, this confirms that your playbook ran perfectly and the containers were created exactly as intended. Since the container creation task was the last one in the playbook, the fact that it completed without errors means everything else went smoothly as well. You’re now ready to start using these containers, and you can even expand or modify your playbook for future deployments or configurations. Everything you’ve automated is repeatable and can be adapted for any new servers or different setups you might need. All in all, this is a huge time-saver, and you’re officially ready to manage Docker containers across your infrastructure!

Check out the Ansible Playbook Webinar Series for more insights.

Conclusion

In conclusion, automating Docker installation and setup on Ubuntu 18.04 with Ansible is a powerful way to streamline server configuration and ensure consistency across your infrastructure. By creating and running an Ansible playbook, you can efficiently install necessary packages, configure Docker, and deploy containers automatically, all while minimizing human error. This method not only saves valuable time but also promotes a standardized approach for managing multiple servers. As containerization continues to grow in popularity, tools like Ansible will remain essential for simplifying the process of server automation. Embrace the power of automation, and you’ll be ready to scale your Docker environments with ease.Snippet for search results: Master Docker installation on Ubuntu 18.04 using Ansible. Automate server setup, reduce human error, and ensure consistency with reusable playbooks.

Automate Docker Setup with Ansible on Ubuntu 22.04

Alireza Pourmahdavi

I’m Alireza Pourmahdavi, a founder, CEO, and builder with a background that combines deep technical expertise with practical business leadership. I’ve launched and scaled companies like Caasify and AutoVM, focusing on cloud services, automation, and hosting infrastructure. I hold VMware certifications, including VCAP-DCV and VMware NSX. My work involves constructing multi-tenant cloud platforms on VMware, optimizing network virtualization through NSX, and integrating these systems into platforms using custom APIs and automation tools. I’m also skilled in Linux system administration, infrastructure security, and performance tuning. On the business side, I lead financial planning, strategy, budgeting, and team leadership while also driving marketing efforts, from positioning and go-to-market planning to customer acquisition and B2B growth.

Caasify
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.