Merakit-Deploy/wordpress/DESTROY.md

7.9 KiB

WordPress Deployment Destruction Guide

This document explains how to destroy WordPress deployments using the config-based destruction system.

Overview

The WordPress deployment system now automatically saves configuration for each successful deployment in the deployments/ directory. These configurations can be used to cleanly destroy environments, removing all associated resources.

Deployment Config Repository

Each successful deployment creates a JSON config file in deployments/ containing:

  • Subdomain and URL: Deployment identifiers
  • Docker Resources: Container names, volumes, networks
  • DNS Information: Cloudflare record ID and IP address
  • Database Details: Database name and user
  • Timestamps: When the deployment was created

Example config file: deployments/my-site_20251217_120000.json

{
  "subdomain": "my-site",
  "url": "my-site.example.com",
  "domain": "example.com",
  "compose_project_name": "my-site",
  "db_name": "wp_db_my_site",
  "db_user": "wp_user_my_site",
  "deployment_timestamp": "2025-12-17T12:00:00",
  "dns_record_id": "abc123xyz",
  "dns_ip": "203.0.113.1",
  "containers": ["my-site_wp", "my-site_db"],
  "volumes": ["my-site_db_data", "my-site_wp_data"],
  "networks": ["my-site_internal"],
  "env_file_path": "/path/to/.env"
}

Using the Destroy Script

Prerequisites

Set the following environment variables (required for DNS cleanup):

export CLOUDFLARE_API_TOKEN="your_token"
export CLOUDFLARE_ZONE_ID="your_zone_id"

If these are not set, the script will still work but DNS records won't be removed.

List All Deployments

View all tracked deployments:

./destroy.py --list

This displays a table with:

  • Subdomain
  • URL
  • Deployment timestamp
  • Config file name

Destroy a Deployment

./destroy.py --subdomain my-site

By URL

./destroy.py --url my-site.example.com

By Config File

./destroy.py --config deployments/my-site_20251217_120000.json

Options

Skip Confirmation

Use -y or --yes to skip the confirmation prompt:

./destroy.py --subdomain my-site --yes

Dry Run

Preview what would be destroyed without making changes:

./destroy.py --subdomain my-site --dry-run

Keep Config File

By default, the config file is deleted after destruction. To keep it:

./destroy.py --subdomain my-site --keep-config

Debug Mode

Enable verbose logging:

./destroy.py --subdomain my-site --log-level DEBUG

What Gets Destroyed

The destroy script removes the following resources in order:

  1. Docker Containers

    • Stops all containers
    • Removes containers forcefully
  2. Docker Volumes

    • Removes database volume (e.g., project_db_data)
    • Removes WordPress volume (e.g., project_wp_data)
  3. Docker Networks

    • Removes internal networks
    • Skips external networks like proxy
  4. DNS Records

    • Removes the Cloudflare DNS record using the saved record ID
    • Requires Cloudflare credentials
  5. Config File

    • Deletes the deployment config file (unless --keep-config is used)

Safety Features

Confirmation Prompt

By default, the script asks for confirmation before destroying:

Are you sure you want to destroy my-site.example.com? [y/N]

Dry-Run Mode

Test the destruction process without making changes:

./destroy.py --subdomain my-site --dry-run

This shows exactly what commands would be executed.

Graceful Failures

  • If DNS credentials are missing, the script continues and skips DNS cleanup
  • If a resource doesn't exist, the script logs a warning and continues
  • Partial failures are reported, allowing manual cleanup of remaining resources

Exit Codes

  • 0: Success
  • 1: Failure (partial or complete)
  • 2: Deployment not found
  • 130: User cancelled (Ctrl+C)

Examples

Example 1: Clean Destruction

# List deployments
./destroy.py --list

# Destroy with confirmation
./destroy.py --subdomain test-site

# Output:
# Deployment Information:
#   Subdomain:     test-site
#   URL:           test-site.example.com
#   Project:       test-site
#   Deployed:      2025-12-17T12:00:00
#   Containers:    2
#   DNS Record ID: abc123
#
# Are you sure you want to destroy test-site.example.com? [y/N]: y
#
# ═══ Destroying Containers ═══
# Stopping container: test-site_wp
# Removing container: test-site_wp
# ...
#
# ✓ Destruction Successful!

Example 2: Batch Destruction

Destroy multiple deployments in one command:

#!/bin/bash
# destroy_all.sh - Destroy all test deployments

for subdomain in test-1 test-2 test-3; do
  ./destroy.py --subdomain "$subdomain" --yes
done

Example 3: Conditional Destruction

Destroy deployments older than 7 days:

#!/bin/bash
# cleanup_old.sh

for config in deployments/*.json; do
  age=$(( ($(date +%s) - $(stat -c %Y "$config")) / 86400 ))
  if [ $age -gt 7 ]; then
    echo "Destroying $config (age: $age days)"
    ./destroy.py --config "$config" --yes
  fi
done

Troubleshooting

"Deployment not found"

The deployment config doesn't exist. Check available deployments:

./destroy.py --list

"Failed to remove DNS record"

Possible causes:

  • Cloudflare credentials not set
  • DNS record already deleted
  • Invalid record ID in config

The script will continue and clean up other resources.

"Command failed: docker stop"

Container might already be stopped. The script continues with removal.

Containers Still Running

If containers aren't removed, manually stop them:

docker ps | grep my-site
docker stop my-site_wp my-site_db
docker rm my-site_wp my-site_db

Volumes Not Removed

Volumes may be in use by other containers:

docker volume ls | grep my-site
docker volume rm my-site_db_data my-site_wp_data

Integration with Deployment

The deployment orchestrator automatically saves configs after successful deployments. The config is saved in deployments/ with the format:

deployments/{subdomain}_{timestamp}.json

This happens automatically in wordpress_deployer/orchestrator.py after Phase 5 (Health Check) completes successfully.

Advanced Usage

Manual Config Creation

If you need to create a config manually for an existing deployment:

from wordpress_deployer.deployment_config_manager import (
    DeploymentConfigManager,
    DeploymentMetadata
)

manager = DeploymentConfigManager()

metadata = DeploymentMetadata(
    subdomain="my-site",
    url="my-site.example.com",
    domain="example.com",
    compose_project_name="my-site",
    db_name="wp_db",
    db_user="wp_user",
    deployment_timestamp="2025-12-17T12:00:00",
    dns_record_id="abc123",
    dns_ip="203.0.113.1",
    containers=["my-site_wp", "my-site_db"],
    volumes=["my-site_db_data", "my-site_wp_data"],
    networks=["my-site_internal"],
    env_file_path="/path/to/.env"
)

manager.save_deployment(metadata)

Programmatic Destruction

Use the destroy script in Python:

import subprocess
import sys

result = subprocess.run(
    ["./destroy.py", "--subdomain", "my-site", "--yes"],
    capture_output=True,
    text=True
)

if result.returncode == 0:
    print("Destruction successful")
else:
    print(f"Destruction failed: {result.stderr}")
    sys.exit(1)

Best Practices

  1. Always Test with Dry-Run: Use --dry-run first to preview destruction
  2. Keep Config Backups: Use --keep-config for audit trails
  3. Verify Before Batch Operations: List deployments before bulk destruction
  4. Monitor Partial Failures: Check logs for resources that weren't cleaned up
  5. Set Cloudflare Credentials: Always configure DNS credentials to ensure complete cleanup

See Also