--- - name: Cleanup All Containers and Networks on Production Server hosts: production become: no gather_facts: yes vars: cleanup_volumes: true # Set to false to preserve volumes tasks: - name: Set stacks_base_path if not defined set_fact: stacks_base_path: "{{ stacks_base_path | default('/home/deploy/deployment/stacks') }}" - name: Display cleanup warning debug: msg: - "=== WARNING: This will stop and remove ALL containers ===" - "Volumes will be removed: {{ cleanup_volumes }}" - "This will cause downtime for all services" - "Stacks path: {{ stacks_base_path }}" - "" - name: List all running containers before cleanup command: docker ps --format 'table {{ "{{" }}.Names{{ "}}" }}\t{{ "{{" }}.Status{{ "}}" }}\t{{ "{{" }}.Ports{{ "}}" }}' register: containers_before changed_when: false - name: Display running containers debug: msg: "{{ containers_before.stdout_lines }}" # Stop all Docker Compose stacks - name: Stop Traefik stack command: docker compose -f {{ stacks_base_path }}/traefik/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/traefik" ignore_errors: yes register: traefik_stop - name: Stop Gitea stack command: docker compose -f {{ stacks_base_path }}/gitea/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/gitea" ignore_errors: yes - name: Stop PostgreSQL Production stack command: docker compose -f {{ stacks_base_path }}/postgresql-production/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/postgresql-production" ignore_errors: yes - name: Stop PostgreSQL Staging stack command: docker compose -f {{ stacks_base_path }}/postgresql-staging/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/postgresql-staging" ignore_errors: yes - name: Stop Redis stack command: docker compose -f {{ stacks_base_path }}/redis/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/redis" ignore_errors: yes - name: Stop Docker Registry stack command: docker compose -f {{ stacks_base_path }}/registry/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/registry" ignore_errors: yes - name: Stop MinIO stack command: docker compose -f {{ stacks_base_path }}/minio/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/minio" ignore_errors: yes - name: Stop Monitoring stack command: docker compose -f {{ stacks_base_path }}/monitoring/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/monitoring" ignore_errors: yes - name: Stop Production stack command: docker compose -f {{ stacks_base_path }}/production/docker-compose.base.yml -f {{ stacks_base_path }}/production/docker-compose.production.yml down args: chdir: "{{ stacks_base_path }}/production" ignore_errors: yes - name: Stop Staging stack command: docker compose -f {{ stacks_base_path }}/staging/docker-compose.base.yml -f {{ stacks_base_path }}/staging/docker-compose.staging.yml down args: chdir: "{{ stacks_base_path }}/staging" ignore_errors: yes - name: Stop WireGuard stack command: docker compose -f {{ stacks_base_path }}/wireguard/docker-compose.yml down args: chdir: "{{ stacks_base_path }}/wireguard" ignore_errors: yes # Remove all containers (including stopped ones) - name: Get all container IDs command: docker ps -a -q register: all_containers changed_when: false - name: Remove all containers command: docker rm -f {{ item }} loop: "{{ all_containers.stdout_lines }}" when: all_containers.stdout_lines | length > 0 ignore_errors: yes # Check for port conflicts - name: Check what's using port 80 command: sudo ss -tlnp 'sport = :80' register: port_80_check changed_when: false ignore_errors: yes - name: Display port 80 status debug: msg: "{{ port_80_check.stdout_lines if port_80_check.rc == 0 else 'Port 80 is free or cannot be checked' }}" - name: Check what's using port 443 command: sudo ss -tlnp 'sport = :443' register: port_443_check changed_when: false ignore_errors: yes - name: Display port 443 status debug: msg: "{{ port_443_check.stdout_lines if port_443_check.rc == 0 else 'Port 443 is free or cannot be checked' }}" # Clean up networks - name: Remove traefik-public network community.docker.docker_network: name: traefik-public state: absent ignore_errors: yes - name: Remove app-internal network community.docker.docker_network: name: app-internal state: absent ignore_errors: yes - name: Get all custom networks command: docker network ls --format '{{ "{{" }}.Name{{ "}}" }}' register: all_networks changed_when: false - name: Remove custom networks (except default ones) community.docker.docker_network: name: "{{ item }}" state: absent loop: "{{ all_networks.stdout_lines }}" when: - item not in ['bridge', 'host', 'none'] - item not in ['traefik-public', 'app-internal'] # Already removed above ignore_errors: yes # Clean up volumes (if requested) - name: Get all volumes command: docker volume ls -q register: all_volumes changed_when: false when: cleanup_volumes | bool - name: Remove all volumes command: docker volume rm {{ item }} loop: "{{ all_volumes.stdout_lines }}" when: - cleanup_volumes | bool - all_volumes.stdout_lines | length > 0 ignore_errors: yes # Final verification - name: List remaining containers command: docker ps -a register: containers_after changed_when: false - name: Display remaining containers debug: msg: "{{ containers_after.stdout_lines }}" - name: List remaining networks command: docker network ls register: networks_after changed_when: false - name: Display remaining networks debug: msg: "{{ networks_after.stdout_lines }}" - name: Verify ports 80 and 443 are free command: sudo ss -tlnp 'sport = :{{ item }}' register: port_check changed_when: false failed_when: port_check.rc == 0 and port_check.stdout_lines | length > 0 loop: - 80 - 443 - name: Display cleanup summary debug: msg: - "=== Cleanup Complete ===" - "All containers stopped and removed" - "Networks cleaned up" - "Volumes removed: {{ cleanup_volumes }}" - "" - "Next steps:" - "1. Run sync-stacks.yml to sync configurations" - "2. Run setup-infrastructure.yml to deploy fresh infrastructure"