How to automate Docker resource cleanup with Python
The real-world scenario
Imagine it is Friday afternoon. You are trying to push a critical hotfix, but your CI/CD pipeline fails with the dreaded **No space left on device** error. You realize your build agent is cluttered with hundreds of dangling images, stopped containers from failed tests, and orphaned volumes. Manually running cleanup commands is a temporary fix that you will inevitably forget to do next week.
Think of this automation script as a **smart janitor** for your infrastructure. Instead of a sledgehammer approach that deletes everything, this script selectively identifies and removes only the “trash”—resources that are older than a specific threshold or in a specific state—ensuring your production environment stays lean without losing important data.
The solution
We will use the official **Docker SDK for Python** to interface with the **Docker Daemon**. The script connects via the default unix socket, inspects the metadata of all resources, calculates their age, and executes a surgical strike on stale assets. This approach is safer than shell scripts because it handles API exceptions gracefully and allows for complex filtering logic (like age-based retention) that the standard **docker prune** command lacks.
Prerequisites
- Install the Docker SDK for Python:
pip install docker - Ensure the **Docker Desktop** or **Docker Engine** is running.
- Python 3.8 or higher.
The code
"""
-----------------------------------------------------------------------
Authors: Sharanam & Vaishali Shah
Recipe: Docker Smart Purge
Intent: Automate the removal of stale containers, images, and volumes based on age.
-----------------------------------------------------------------------
"""
import docker
from datetime import datetime, timezone
import sys
def purge_docker_resources(days_threshold=7):
try:
# Initialize the Docker client from environment variables
client = docker.from_env()
now = datetime.now(timezone.utc)
print(f"--- Starting Docker Cleanup (Threshold: {days_threshold} days) ---")
# 1. Clean up stopped containers
containers = client.containers.list(all=True, filters={'status': 'exited'})
for container in containers:
# Docker timestamps are in ISO format
created_at = datetime.fromisoformat(container.attrs['Created'][:19]).replace(tzinfo=timezone.utc)
age = (now - created_at).days
if age >= days_threshold:
print(f"Removing container: {container.short_id} (Age: {age} days)")
container.remove(force=True)
# 2. Clean up dangling images
# Dangling images are those with no tag and not referenced by any container
dangling_images = client.images.list(filters={'dangling': True})
for image in dangling_images:
print(f"Removing dangling image: {image.short_id}")
try:
client.images.remove(image.id, force=True)
except docker.errors.APIError:
print(f"Skipping image {image.short_id}: currently in use.")
# 3. Clean up unused volumes
volumes = client.volumes.list(filters={'dangling': True})
for volume in volumes:
print(f"Removing unused volume: {volume.name}")
try:
volume.remove(force=True)
except docker.errors.APIError:
print(f"Skipping volume {volume.name}: currently in use.")
print("--- Cleanup Complete ---")
except docker.errors.DockerException as e:
print(f"Error: Could not connect to Docker. Is it running? n{e}")
sys.exit(1)
except Exception as e:
print(f"An unexpected error occurred: {e}")
sys.exit(1)
if __name__ == "__main__":
# You can pass the number of days as a threshold
purge_docker_resources(days_threshold=7)
Code walkthrough
The logic follows a structured path to ensure safety and efficiency:
- Initialize Client: We use
docker.from_env(), which automatically looks for the **DOCKER_HOST** and local sockets, making it compatible with both Linux and Windows. - Time Calculation: We convert the Docker **Created** timestamp into a Python **datetime** object. By setting the timezone to **UTC**, we avoid bugs related to local server time shifts.
- Container Filtering: We specifically target containers with the status **exited**. This prevents the script from accidentally stopping active services.
- Image Pruning: We target **dangling** images. These are layers that no longer have a relationship to a tagged image, often left behind after a new
docker build. - Error Handling: The script uses
try-exceptblocks around the removal calls. This is crucial because Docker might lock a resource if another process suddenly accesses it, and we don’t want the entire script to crash.
Sample output
When you run the script in your **Terminal** or **PowerShell**, you will see a summary of the deleted items:
--- Starting Docker Cleanup (Threshold: 7 days) ---
Removing container: a1b2c3d4 (Age: 12 days)
Removing container: e5f6g7h8 (Age: 9 days)
Removing dangling image: sha256:88234...
Removing unused volume: web_cache_data
--- Cleanup Complete ---
Conclusion
Managing disk space in a containerized environment does not have to be a manual chore. By using this Python script, you can schedule a cron job or a scheduled task to keep your development machines and build servers running at peak performance. This automation ensures that your infrastructure remains healthy, allowing you to focus on writing code rather than troubleshooting disk errors.
🚀 Don’t Just Learn Docker — Master It.
This tutorial was just the tip of the iceberg. To truly advance your career and build professional-grade systems, you need the full architectural blueprint.
My book, The Polyglot Playbook with Docker and AI for Beginners, takes you from “making it work” to “making it scale.” I cover advanced patterns, real-world case studies, and the industry best practices that senior engineers use daily.