I'm using with_sequence to iteratively create copies of a container on a single node using ansible. The number of containers is determined by a variable set at the time of deploy. This works well for increasing the number of containers to scale up, but when I reduce the number to deploy less containers the old containers are left running. Is there a way to stop the old containers? Prune won't seem to work correctly since the old containers aren't stopped.

1 Answers

0
larsks On

One option is to move from Ansible to docker-compose, which knows how to scale up and scale down (and honestly provides a better use experience for manage complex Docker configurations).

Another idea would be to include one loop for starting containers, and then a second loop that attempts to remove containers up to some maximum number, like this (assuming the number of containers you want to start is in the ansible variable container_count):

---
- hosts: localhost
  gather_facts: false
  vars:
    container_count: 4
    maximum_containers: 20
  tasks:
    - name: Start containers
      docker_container:
        state: present
        name: "service-{{ item }}"
        image: fedora
        command: "sleep inf"
      loop: "{{ range(container_count|int)|list }}"

    - name: Stop containers
      docker_container:
        state: absent
        name: "service-{{ item }}"
      loop: "{{ range(container_count|int, maximum_containers|int)|list }}"

Called with the default values defined in the playbook, it would create 4 containers and then attempt to delete 16 more. This is going to be a little slow, since Ansible doesn't provide any way to prematurely exit a loop, but it will work.

A third option is to replace the "Stop containers" task with a shell script, which might be slightly faster but less "ansible-like":

---
- hosts: localhost
  gather_facts: false
  vars:
    container_count: 4
  tasks:
    - name: Start containers
      docker_container:
        state: present
        name: "service-{{ item }}"
        image: fedora
        command: "sleep inf"
      loop: "{{ range(container_count|int)|list }}"

    - name: Stop containers
      shell: |
        let i={{ container_count }}
        while :; do
          name="service-$i"
          docker rm -f $name || break
          echo "removed $name"
          let i++
        done
        echo "all done."

Same idea, but somewhat faster and it doesn't require you to define a maximum container count.