Managing dockers using ansible on Synology NAS
Synology NAS devices are great and easy to use devices. The model I use is plenty strong to running a few containers as well. However, the Synology Docker application is not the best when it comes to managing multiple containers. It is a bit clunky and does not provide the flexibility I want.
Managing containers is very well possible using Ansible. Especially when you already use it for different systems and different tasks. Adding a playbook to allow you to update or manage your containers is a no-brainer.
Let's start with the setup, and leave synology aside for a moment.
I wanted to extend my playbook for updating my servers, including the containers running on them.
The playbook
I have added the following part to my playbook:
- name: Update docker compose
hosts: dockerCompose
become: true
roles:
- { role: docker_compose, tags: docker_compose }
This will run the docker_compose
role on the dockerCompose
hosts. The become: true
allows the playbook to run with elevated privileges, which is required to manage docker containers.
The hosts
The hosts are defined in my hosts.yaml
file:
The role docker_compose
The role docker_compose
is defined in my Ansible roles directory. The role contains the tasks to manage the docker containers, using the docker_compose_v2 module.
The roles/docker_compose/tasks/main.yml
looks like this:
---
- name: Update dockers
become: true
community.docker.docker_compose_v2:
docker_cli: "{{ docker_cli | default(omit) }}"
project_src: "{{ item.path }}"
remove_orphans: true
state: restarted
loop: "{{ dockers }}"
This tasks will loop over the dockers
variable, which is defined in the hostvars
. This will have the paths to the docker compose files that need to be managed.
dockers:
- path: /path/to/project/holding/docker-compose_file
- path: /path/to/project1/holding/docker-compose_file
- path: /path/to/project2/holding/docker-compose_file
The state: restarted
will ensure that the containers are restarted after pulling the latest images. The remove_orphans: true
will remove any containers that are no longer defined in the docker compose file.
The docker_cli
variable is optional and can be used to specify the docker CLI command to use. If not set, it will use the default docker compose
command. For my synology I had to specify it.
Specify the docker_cli
variable in the host_vars
file for the Synology NAS:
Docker Compose Plugin
In the past, I had to do certain modifications to the synology python environment to be able to achieve this. Now I have modified the setup to use the compose plugin. Especially, that since 2022 the docker-compose
command is deprecated and replaced by the docker compose
command. The community.docker.docker_compose_v2
module will use the newer docker compose
command, based on the plugin.
This plugin needs to be installed on the Synology NAS. I have created the following task to install the plugin.
In the same role, roles/docker_compose/tasks/synology.yml
:
---
- name: Create a docker plugins directory
ansible.builtin.file:
path: "{{ docker_plugins_path }}"
state: directory
mode: "0755"
- name: Download docker compose plugin
ansible.builtin.get_url:
url: https://github.com/docker/compose/releases/download/{{ docker_compose_version }}/docker-compose-linux-x86_64
dest: "{{ docker_plugins_path }}/docker-compose"
mode: "0755"
The following are added to the hostvars
:
Playbook addition
To call this task, we add the following to the playbook, before calling the docker_compose
role:
- name: Docker compose for Synology hosts
hosts: synology
become: true
tasks:
- name: Include Synology tasks
ansible.builtin.include_tasks: roles/docker_compose/tasks/synology.yml
Conclusion
Using Ansible to manage docker containers on a Synology NAS is a great way to automate the management of your containers. It allows you to easily update and manage your containers, without having to use the Synology Docker application. The community.docker.docker_compose_v2
module provides a simple way to manage your containers using the newer docker compose
command, which is the recommended way to manage docker containers.
Complete files
update_servers.yaml playbook
---
- name: Docker compose for Synology hosts
hosts: synology
become: true
tasks:
- name: Include Synology tasks
ansible.builtin.include_tasks: roles/docker_compose/tasks/synology.yml
- name: Update docker compose
hosts: dockerCompose
become: true
roles:
- { role: docker_compose, tags: docker_compose }
roles/docker_compose/tasks/main.yml
---
- name: Install dependencies
ansible.builtin.command:
cmd: "{{ item.install_command }}"
chdir: "{{ item.path }}"
loop: "{{ dockers }}"
when: item.install_command is defined
register: my_output
changed_when: my_output.rc != 0 # <- Uses the return code to define when the task has changed.
become_user: "{{ user.name }}"
become: true
- name: Update dockers
become: true
community.docker.docker_compose_v2:
docker_cli: "{{ docker_cli | default(omit) }}"
project_src: "{{ item.path }}"
remove_orphans: true
state: present
ignore_build_events: false
loop: "{{ dockers }}"
roles/docker_compose/tasks/synology.yml
---
- name: Create a docker plugins directory
ansible.builtin.file:
path: "{{ docker_plugins_path }}"
state: directory
mode: "0755"
- name: Download docker compose plugin
ansible.builtin.get_url:
url: https://github.com/docker/compose/releases/download/{{ docker_compose_version }}/docker-compose-linux-x86_64
dest: "{{ docker_plugins_path }}/docker-compose"
mode: "0755"
host_vars/hostname1/main.yaml
dockers:
- path: /path/to/project/holding/docker-compose_file
- path: /path/to/project1/holding/docker-compose_file
- path: /path/to/project2/holding/docker-compose_file
docker_cli: /usr/local/bin/docker
docker_compose_version: v2.37.1
docker_plugins_path: /usr/local/lib/docker/cli-plugins