Deploy docker-compose Using Ansible

Ansible has a great way to create reusable blocks of playbooks as roles to configure systems. One really nice feature of ansible is the amazing community of ansible collections and roles found on Ansible Galaxy. One author I’ve been following for some time is Jeff Geerling who has a large amount of really well written roles for use. This guide will show you how to utilize other ansible galaxy roles and collections to create a docker-compose deployment role and playbook.

Buckle up, this is going to be a fun one!

Ensure you install ansible with your preferred method. If you don’t know what that means, consult the ansible documentation to get the package installed properly.

Now that you have ansible installed, create some directories. I am going to include the following commands a bash examples. These commands set up the structure of this example’s project. This should be translated to your native tongue.

# Create the project directory
mkdir -p ansible-calm-seas
mkdir -p ansible-calm-seas/roles
mkdir -p ansible-calm-seas/collections
mkdir -p ansible-calm-seas/roles/compose
mkdir -p ansible-clam-seas/roles/compose/tasks
mkdir -p ansible-clam-seas/roles/compose/templates

This should create a basic directory structure for your playbook. Now we will create files. Please be mindful of the paths in each example code block below.

First we will create our requirements file for our ansible collections and roles we need installed. We will be using ansible community collections to accomplish our desired docker-compose operations, as well as an ansible role made by our previously mentioned friend, Jeff Geerling.

First let’s populate: ansible-calm-seas/collections/requirements.yml

---

collections:
  - name: community.docker

This file will tell ansible to install the community.docker collection. We will install this collection later.

Now populate: ansible-calm-seas/roles/requirements.yml

---

roles:
  - name: geerlingguy.docker

This will tell ansible to install geerlingguy.docker, a handy role to install and maintain docker and docker-compose on a system.

Let’s run the following commands on your command line to install the role and collection:

ansible-galaxy collection install -r ansible-calm-seas/collections/requirements.yml
ansible-galaxy role install -r ansible-calm-seas/roles/requirements.yml

You should see the collection and role install finish. If it warns about it already installed, you can use force to reinstall these modules. Let’s move forward and create the compose role.

Edit the following file: ansible-calm-seas/roles/compose/templates/docker-compose.yml.j2

{{ compose | to_yaml }}

The above file will take an ansible var called compose and convert it to yaml. Because our docker-compose file is yaml already, we can utilize this to work with native ansible data structures.

Let’s continue to create the tasks involved with the compose role. Edit the following file: ansible-calm-seas/roles/compose/tasks/main.yml

---

- name: Install python3-pip
  ansible.builtin.apt:
    name: python3-pip
    state: present

- name: Install docker-compose pip
  ansible.builtin.pip:
    name: docker-compose
    state: present

- name: Ensure project directory exists
  ansible.builtin.file:
    path: "{{ project_dir }}"
    owner: root
    group: root
    mode: "0755"
    state: directory

- name: Render docker-compose
  ansible.builtin.template:
    src: docker-compose.yml.j2
    dest: "{{ project_dir }}/docker-compose.yml"
    owner: root
    group: root
    mode: "0600"

- name: Deploy docker container
  community.docker.docker_compose:
    project_src: "{{ project_dir }}"
    pull: true
    state: present
  register: output

These tasks will ensure python3-pip is installed, docker-compose is installed via pip, creates a project directory, renders and deploys a docker-compose file.

Now that we have a decent set of tasks ready to go, let’s finally create our playbook and inventory file.

Create: ansible-calm-seas/main.yml

---

- name: Deploy a docker-compose container with ansible
  hosts: all
  become: true
  gather_facts: true
  become_method: sudo
  roles:
    - geerlingguy.docker
    - compose
  tasks:
    - name: Create a calm hello world file
      copy:
        dest: "{{project_dir}}/index.html"
        content: |
          <p><a href="https://nickthegray.com><img src="https://nickthegray.com/wp-content/uploads/2023/02/DALL·E-2023-02-24-02.31.29-a-ship-set-to-sea-digital-art.png"></p>
          <p>Calm digital seas</p>
  vars:
    project_dir: /opt/calm-seas
    compose:
      version: '3'
      nginx:
        image: nginx:latest
        volumes:
          - "{{ project_dir }}/index.html:/usr/share/nginx/html/index.html"
        ports:
          - 8899:80

Now create: ansible-calm-seas/inventory.yml

Note, you will need to configure this file according to your own homelab specifications.

---

all:
  children:
    calm_seas:
      hosts:
        calm-seas-0:
          ansible_host: 192.168.111.50 # change this to your host!

Now you can use the ansible-playbook command to run the playbook!

cd ansible-calm-seas
ansible-playbook main.yml -i inventory.yml

This should create a project and publish a simple webpage on port 8899.

I hope this tutorial helped unlock some information regarding ansible and deploying a docker-compose file on a remote server. It really does make the setup simple to take a base machine to completely deployed with very little lines. Enjoy the example and have a great day.

Leave a Reply

Your email address will not be published. Required fields are marked *