The nightly prune ran `docker system prune -a`, which deletes every image no local container uses, so each swarm node kept only its own tasks' images. When the other node failed or was drained, its services had to pull first: on 2026-10-25 Traefik took 11.5 min to start on Docker03. maintenance/swarm_prune.yml (built in) prunes stopped containers, unused networks, dangling images and build cache, then removes only the images that no container uses and no swarm service is pinned to, wherever that service runs. Old digests left by redeploys still go. - A container's image is kept by its id and by the reference it was made from, since on the containerd store the id alone hasn't held a tag. - A node that can't list the swarm's services removes no images and fails rather than pruning blind. - Check mode lists what would go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
44 lines
1.9 KiB
YAML
44 lines
1.9 KiB
YAML
---
|
|
# description: Reclaim disk on swarm nodes but keep every image a swarm service is pinned to, so each node can take over the others' services without pulling.
|
|
# steward:category: maintenance
|
|
# steward:confirm: true
|
|
# Run on the swarm's nodes; each must be a manager (only a manager can list
|
|
# services). On each node:
|
|
# 1. docker system prune: stopped containers, unused networks, dangling
|
|
# images, build cache (+ prune_volumes=true: unused anonymous volumes).
|
|
# 2. files/swarm_prune.py: removes every other image no container uses and
|
|
# no swarm service is pinned to, wherever that service's task runs. A
|
|
# node keeps the images for the services running elsewhere, so it can
|
|
# start them at once when the other node fails or is drained.
|
|
# A node that can't list the swarm's services removes no images and the run
|
|
# fails, rather than pruning blind. Check mode lists what would go.
|
|
- name: Swarm prune
|
|
hosts: all
|
|
gather_facts: false
|
|
become: true
|
|
vars:
|
|
prune_volumes: false
|
|
tasks:
|
|
- name: Prune stopped containers, unused networks, dangling images and build cache
|
|
ansible.builtin.command:
|
|
argv: >-
|
|
{{ ['docker', 'system', 'prune', '-f']
|
|
+ (['--volumes'] if prune_volumes | bool else []) }}
|
|
register: system_prune
|
|
changed_when: "'Total reclaimed space: 0B' not in system_prune.stdout"
|
|
|
|
- name: Remove images no container uses and no swarm service is pinned to
|
|
ansible.builtin.script:
|
|
cmd: "swarm_prune.py{{ ' --dry-run' if ansible_check_mode else '' }}"
|
|
executable: python3
|
|
check_mode: false
|
|
register: image_prune
|
|
changed_when: >-
|
|
not ansible_check_mode and (image_prune.stdout | from_json).removed | default([]) | length > 0
|
|
|
|
- name: Report what went
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
{{ (system_prune.stdout_lines | default([]) | select | list)[-1:]
|
|
+ [image_prune.stdout | from_json] }}
|