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
By Subdomain (Recommended)
./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:
-
Docker Containers
- Stops all containers
- Removes containers forcefully
-
Docker Volumes
- Removes database volume (e.g.,
project_db_data) - Removes WordPress volume (e.g.,
project_wp_data)
- Removes database volume (e.g.,
-
Docker Networks
- Removes internal networks
- Skips external networks like
proxy
-
DNS Records
- Removes the Cloudflare DNS record using the saved record ID
- Requires Cloudflare credentials
-
Config File
- Deletes the deployment config file (unless
--keep-configis used)
- Deletes the deployment config file (unless
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: Success1: Failure (partial or complete)2: Deployment not found130: 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
- Always Test with Dry-Run: Use
--dry-runfirst to preview destruction - Keep Config Backups: Use
--keep-configfor audit trails - Verify Before Batch Operations: List deployments before bulk destruction
- Monitor Partial Failures: Check logs for resources that weren't cleaned up
- Set Cloudflare Credentials: Always configure DNS credentials to ensure complete cleanup
See Also
- Main README - Deployment documentation
- deploy.py - Deployment script
- wordpress_deployer/ - Core deployment modules