this is my first ansible playbook.

it installs docker in swarm mode and automatically joins the cluster.

could you guys please review my code and show me where it can be improved?

- hosts: all
    - name: Add apt key
        url: https://download.docker.com/linux/raspbian/gpg
        state: present

    - name: Remove some packages
        autoclean: yes
        autoremove: yes
        state: absent
        pkg: [python2, python-configparser, python-is-python2]

    - name: Install a list of packages
        update_cache: yes
          - apt-transport-https
          - aptitude
          - ca-certificates
          - curl
          - libffi-dev
          - libssl-dev
          - python3
          - python-is-python3
          - software-properties-common

    - name: Get docker convenience script
      shell: curl -fsSL https://get.docker.com -o get-docker.sh
        creates: ~/get-docker.sh

    - name: Install docker
      shell: sh ~/get-docker.sh
        creates: /usr/bin/docker

    - name: Config user permissions
      user: name="{{ ansible_user_id }}" groups=docker append=yes generate_ssh_key=yes
      #shell: usermod -aG docker $(whoami)

    - name: Install docker-compose
      pip: name=docker-compose state=latest
      #shell: pip3 -v install -U docker-compose
      #  creates: /usr/local/bin/docker-compose

    - name: Start service
      service: name=docker enabled=yes state=started

    - name: Get docker info
      shell: docker info
      register: docker_info
      changed_when: False

- hosts: docker_swarm_manager
    - name: Create primary swarm manager
      shell: docker swarm init --advertise-addr {{ ansible_default_ipv4.address }}
      when: "docker_info.stdout.find('Swarm: inactive') > 0"

    - name: Get docker swarm manager ip
        content: '{{ ansible_default_ipv4.address }}'
        dest: '/tmp/dsm_ip'

    - name: Get docker swarm manager token
      shell: docker swarm join-token -q manager
      register: swarm_manager_token
    - copy:
        content: '{{ swarm_manager_token.stdout }}'
        dest: '/tmp/dsm_mt'

    - name: Get docker swarm worker token
      shell: docker swarm join-token -q worker
      register: swarm_worker_token
    - copy:
        content: '{{ swarm_worker_token.stdout }}'
        dest: '/tmp/dsm_wt'

- hosts: all
    - name: Join the swarm
      shell: "docker swarm join --token {{ lookup('file', '/tmp/dsm_mt') }} {{ lookup('file', '/tmp/dsm_ip') }}:2377"
      when: "docker_info.stdout.find('Swarm: inactive') > 0"
      retries: 5
      delay: 5

A couple queries: 1. What version of ansible are you using? 2. Why are you not using the docker_swarm module? – 0xSheepdog

  1. ansible [core 2.11.6]
root@minipc:~# ansible --version

ansible [core 2.11.6] 
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0]
  jinja version = 3.0.3
  libyaml = True
  1. i didnt even know there was a docker_swarm module. maybe you could post an answer showing how you would write the playbook using this module? my playbook was pretty simple to write, if using the module can save time, i dont mind changing.
  • \$\begingroup\$ A couple queries: 1. What version of ansible are you using? 2. Why are you not using the docker_swarm module? \$\endgroup\$
    – 0xSheepdog
    Commented Nov 30, 2021 at 2:48
  • \$\begingroup\$ @0xSheepdog i updated my post to answer your questions \$\endgroup\$
    – RASG
    Commented Nov 30, 2021 at 12:41

1 Answer 1


I have done some Ansible tasks 5 years ago, so I looked at your code just out of interest, and I didn't read any documentation. Here are some things I noted by just looking at the code:

The task apt_key looks strange to me. The basic idea of a GPG key is that it provides a trust anchor. You currently trust the URL of that task to always provide the correct GPG key. Instead, I would download this key and verify offline that it comes from the person it says. Then I'd compute a hash of the file and use that to verify the download. Since the hash by itself does not tell a story, I'd write a comment along it, summarizing the information from the GPG key, something like:

# 2021-11-30: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
# Docker Release (CE deb) <[email protected]>
hash: sha256:abcdef12345678

Verifying the download is something that the apt_key module should provide out-of-the-box, or its documentation must warn about the practice of downloading an untrusted key, otherwise its authors have no clue of IT security.

The task apt looks strange as well. You are basing the system on a Linux distribution that still has Python 2 installed as default. That seems old to me. Isn't there some newer release of that distribution?

Talking of the distribution: From reading the Ansible file, I have no idea what base system I should install before applying Ansible to it. Is it a Debian, Ubuntu, Alpine, Arch, Red Hat (probably not)? This should be documented somewhere. In case the hosts die all of a sudden, it should be possible to set up the exact same setup as before.

Speaking of which, you don't specify which versions of the packages you want to have installed. This also provides possible variance.

Over to get-docker.sh. You trust get.docker.com to always serve you the file you expect. You should verify this download as well, just as you do with the Debian packages above. Also, downloading the now-current file prevents the setup from being reproducible.

Same for pip3, Python packages also have versions, and if you want a reproducible setup, you must use fixed version numbers instead of always taking the latest versions.

I found the filenames in /tmp a bit short. When you wrote the code, it was immediately clear to you what they are supposed to mean, but will that still be the case in 2 years? I'd choose longer, more expressive names.

All the rest looks good, and it serves as a nice and brief instruction how to set up a Docker Swarm cluster.

I wonder how many hosts all means. But that probably depends on how you use this Ansible file. It should definitely not mean "all 2000 reachable hosts that are accidentally reachable". :)

Further reading:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.