--- - name: Docker orphan detection hosts: all become: true gather_facts: false vars: report_root: "/opt/docker-reports" report_timestamp: "{{ lookup('pipe', 'date +%Y%m%d-%H%M%S') }}" report_file_name: "docker_orphan_detection_<< inventory_hostname >>_<< report_timestamp >>.txt" tasks: - name: Ensure report root exists ansible.builtin.file: path: "<< report_root >>" state: directory mode: "0750" - name: List exited containers ansible.builtin.command: docker ps -a --filter status=exited --format "{{.Names}}" register: orphan_exited_containers changed_when: false - name: List dead containers ansible.builtin.command: docker ps -a --filter status=dead --format "{{.Names}}" register: orphan_dead_containers changed_when: false - name: List dangling images ansible.builtin.command: docker images -f dangling=true -q register: orphan_dangling_images changed_when: false - name: List dangling volumes ansible.builtin.command: docker volume ls -qf dangling=true register: orphan_dangling_volumes changed_when: false - name: List dangling networks ansible.builtin.command: docker network ls -qf dangling=true register: orphan_dangling_networks changed_when: false - name: Build orphan report body ansible.builtin.set_fact: docker_orphan_report_body: | Host: << inventory_hostname >> Timestamp: {{ lookup('pipe', 'date -u +%Y-%m-%dT%H:%M:%SZ') }} Exited containers (<< orphan_exited_containers.stdout_lines | length >>): << (orphan_exited_containers.stdout_lines | default([])) | join('\n') if (orphan_exited_containers.stdout_lines | length > 0) else 'none' >> Dead containers (<< orphan_dead_containers.stdout_lines | length >>): << (orphan_dead_containers.stdout_lines | default([])) | join('\n') if (orphan_dead_containers.stdout_lines | length > 0) else 'none' >> Dangling images (<< orphan_dangling_images.stdout_lines | length >>): << (orphan_dangling_images.stdout_lines | default([])) | join('\n') if (orphan_dangling_images.stdout_lines | length > 0) else 'none' >> Dangling volumes (<< orphan_dangling_volumes.stdout_lines | length >>): << (orphan_dangling_volumes.stdout_lines | default([])) | join('\n') if (orphan_dangling_volumes.stdout_lines | length > 0) else 'none' >> Dangling networks (<< orphan_dangling_networks.stdout_lines | length >>): << (orphan_dangling_networks.stdout_lines | default([])) | join('\n') if (orphan_dangling_networks.stdout_lines | length > 0) else 'none' >> - name: Save local orphan detection report ansible.builtin.copy: dest: "<< report_root >>/<< report_file_name >>" content: "<< docker_orphan_report_body >>" mode: "0640" - name: Build Discord report content ansible.builtin.set_fact: discord_orphan_report_content: | << discord_message_prefix | default('Docker Orphan Detection Report') >> ```text << docker_orphan_report_body | truncate(1700, true, '...') >> ``` when: - discord_enabled | default(false) - (discord_webhook_url | default('')) | length > 0 - name: Send orphan report to Discord webhook ansible.builtin.uri: url: "<< discord_webhook_url | default('') >>" method: POST body_format: json body: username: "<< discord_username | default('Docker Reporter') >>" content: "<< discord_orphan_report_content >>" status_code: 204 when: - discord_enabled | default(false) - (discord_webhook_url | default('')) | length > 0