PruneMate
PruneMate - Docker image & resource cleanup helper, on a schedule!
Install / Use
/learn @anoniemerd/PruneMateREADME
PruneMate
<p align="center"> <img width="400" height="400" alt="prunemate-logo" src="https://github.com/user-attachments/assets/0785ea56-88f6-4926-9ae1-de736840c378" /> </p> <h1 align="center">PruneMate</h1> <p align="center"><em>Docker image & resource cleanup helper, on a schedule!</em></p> <p align="center"> <img src="https://img.shields.io/badge/version-1.3.3-purple?style=for-the-badge"/> <img src="https://img.shields.io/badge/python-3.12-yellow?style=for-the-badge&logo=python&logoColor=ffffff"/> <img src="https://img.shields.io/badge/docker-compose-0db7ed?style=for-the-badge&logo=docker&logoColor=ffffff"/> <img src="https://img.shields.io/badge/license-AGPLv3-orange?style=for-the-badge"/> <a href="https://hub.docker.com/r/anoniemerd/prunemate"> <img src="https://img.shields.io/docker/pulls/anoniemerd/prunemate?style=for-the-badge&logo=docker&logoColor=ffffff&label=docker%20pulls"/> </a> <a href="https://www.buymeacoffee.com/anoniemerd"> <img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" alt="Buy Me a Coffee"/> <a href="https://prunemate.org"> <img src="https://img.shields.io/badge/Visit-Website-0ea5e9?style=for-the-badge&logo=internet-explorer&logoColor=white" alt="Website"/> </a> </p>A sleek, lightweight web interface to automatically clean up Docker resources on a schedule. Built with Python (Flask) · Docker SDK · APScheduler · Gunicorn
Keep your Docker host tidy with scheduled cleanup of unused images, containers, networks, and volumes.
⚠️ DISCLAIMER: PruneMate uses Docker's native
prunecommands to delete unused resources. This means it removes containers, images, networks, and volumes that Docker considers "unused" - be careful with volumes as they may contain important data. Ensure you understand what will be pruned before enabling automated schedules. The author is not responsible for any data loss or system issues. Use at your own risk.
✨ Features
- 🕐 Flexible scheduling - Daily, Weekly, or Monthly cleanup runs with optional manual-only mode
- 🔀 Schedule control toggle - Enable/disable automatic scheduling, so PruneMate only runs manually
- 🔍 Prune preview - See exactly what will be deleted before executing manual prune operations
- 🌍 Timezone aware - Configure your local timezone
- 🕒 12/24-hour time format - Choose your preferred time display
- 🐳 Multi-host support - Manage multiple Docker hosts from one interface (requires docker-socket-proxy on remote hosts)
- 🧹 Selective cleanup - Choose what to prune: containers, images, networks, volumes, build cache
- 🏗️ Build cache cleanup - Reclaim significant space by pruning Docker builder cache (often 10GB+)
- 📊 All-Time Statistics - Track cumulative space reclaimed and resources deleted across all runs
- 🏠 Homepage integration - Display statistics in your Homepage dashboard (works with authentication enabled)
- 🎨 Modern UI - Dark theme with smooth animations and responsive design
- 🔒 Secure authentication - Optional login protection with password hashing and Basic Auth support
- 🏗️ Multi-architecture support - Native amd64 and arm64 Docker images (Intel/AMD, Raspberry Pi, Apple Silicon)
- 🔒 Safe & controlled - Manual trigger with preview and detailed logging
- 📈 Detailed reports - See exactly what was cleaned and how much space was reclaimed
📷 Screenshots
Main Dashboard
The overall look and feel of the PruneMate dashboard
<p align="center"> <img width="400" height="800" src="https://github.com/user-attachments/assets/845405f1-0787-4323-a592-36177e32a035" /> </p>Authentication page
The login page, (when enabled in the docker-compose.yaml environment variables)
<p align="center"> <img width="400" height="800" src="https://github.com/user-attachments/assets/29ea359c-452e-4e1d-8567-c8fd65b08d4e" /> </p>External Docker hosts
Add external Docker hosts via docker-socket-proxy
<p align="center"> <img width="400" height="400" alt="prunemate-cleanup" src="https://github.com/user-attachments/assets/28abdbe4-bd9e-4272-a6fc-24a4a8dc83bb" /> </p>Notification Settings
Set up notifications via Gotify, ntfy.sh, Discord, or Telegram to stay informed about cleanup results.
<p align="center"> <img width="400" height="400" alt="prunemate-notifications" src="https://github.com/user-attachments/assets/73a06c4d-fffa-40eb-a010-239d7d364004" /> </p>Prune preview
A brief interface that shows which Docker resources will be pruned during the next cleanup run, either manually triggered or scheduled.
<p align="center"> <img width="400" height="400" alt="prunemate-preview" src="https://github.com/user-attachments/assets/34fb445d-8956-46e8-84df-b6718db3f556" /> </p>🚀 Quick Start with Docker Compose
Prerequisites
- Docker and Docker Compose installed
- Access to Docker socket (
/var/run/docker.sock)
Installation
- Create a
docker-compose.yamlfile:
services:
prunemate:
image: anoniemerd/prunemate:latest # Supports amd64 and arm64
container_name: prunemate
ports:
- "7676:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./logs:/var/log
- ./config:/config
environment:
- PRUNEMATE_TZ=Europe/Amsterdam # Change this to your desired timezone
- PRUNEMATE_TIME_24H=true #false for 12-Hour format (AM/PM)
# Optional: Enable authentication (generate hash with: docker run --rm anoniemerd/prunemate python prunemate.py --gen-hash "password")
# - PRUNEMATE_AUTH_USER=admin
# - PRUNEMATE_AUTH_PASSWORD_HASH=your_base64_encoded_hash_here
restart: unless-stopped
- Start PruneMate:
docker-compose up -d
- Access the web UI of PruneMate:
Open your browser and navigate to:
http://<your-server-ip>:7676/
🚀 Quick Start with Docker Run
Using Docker CLI:
docker run -d \
--name prunemate \
-p 7676:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd)/logs:/var/log \
-v $(pwd)/config:/config \
-e PRUNEMATE_TZ=Europe/Amsterdam \
-e PRUNEMATE_TIME_24H=true \
--restart unless-stopped \
anoniemerd/prunemate:latest
Access the web UI:
http://<your-server-ip>:7676/
Volume explanations:
/var/run/docker.sock- Required for Docker API access./logs- Stores application logs (rotating, 5MB max per file)./config- Stores configuration and state files
⚙️ Configuration
Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| PRUNEMATE_TZ | UTC | Timezone for scheduling (e.g., Europe/Amsterdam, America/New_York) |
| PRUNEMATE_TIME_24H | true | Time format: true for 24-hour, false for 12-hour (AM/PM) |
| PRUNEMATE_CONFIG | /config/config.json | Path to configuration file |
| PRUNEMATE_AUTH_USER | admin | Username for authentication (optional, only used when auth is enabled) |
| PRUNEMATE_AUTH_PASSWORD_HASH | (none) | Base64-encoded password hash (enables authentication when set) |
🔐 Authentication (Optional)
PruneMate supports optional password protection for the web interface and API endpoints.
Key features:
- 🔒 Form-based login - Styled login page matching the app's design
- 🔑 Secure hashing - Passwords are hashed using scrypt (industry standard)
- 🌐 API compatibility - Basic Auth fallback for external tools (Homepage, Dashy, etc.)
- 🚪 Logout button - Convenient session management
To enable authentication:
- Generate a password hash using the built-in tool:
docker run --rm anoniemerd/prunemate:latest python prunemate.py --gen-hash "your_password"
This outputs a Base64-encoded hash (safe for YAML, no special characters):
c2NyeXB0OjMyNzY4Ojg6MSRvcDdnZFlGR1JmRFp4Y1RjJDBmMzNlYzc4NzExZTI4MzllYjk0MWFiOTZkOGUyZGNjNGRhMzU2NTlmMGI1ZDg0NjhjZTdkMThhODhmNmQ3ZGRhOGU4YzdmMDYxMWZiNzAyYjA0ZGNhNTBjZWMxZjFlYzc3ZjhlNzJhYmM0MmQ3OTQ5NDM2MDUzZWRlZjlhZGY0
Why Base64? Raw scrypt hashes contain
$characters that Docker Compose interprets as environment variables, corrupting the hash. Base64 encoding produces alphanumeric strings that YAML handles safely without escaping.
✅ Special characters that work well:
- Hash characters:
#- At sign:
@- Percent:
%- Asterisk:
*- Ampersand:
&- Caret:
^⚠️ Avoid these characters:
- Exclamation mark:
!(bash history expansion)- Dollar sign:
$(variable expansion - even Base64 encoded, can cause issues in some contexts)Safe examples:
MyPassword#123Test@secure%passprunemate&admin^2024MyPass*Admin#99
- Add to your docker-compose.yaml:
environment:
- PRUNEMATE_AUTH_USER=admin # Optional (default: admin)
- PRUNEMATE_AUTH_PASSWORD_HASH=c2NyeXB0OjMyNzY4Ojg6MSRvcDdnZFlGR1JmRFp4Y1RjJDBmMzNlYzc4...
- Restart the container:
docker-compose up -d
Important notes:
- Authentication is opt-in - only enabled when
PRUNEMATE_AUTH_PASSWORD_HASHis set - Without the hash variable, the app runs in open mode (backward compatible)
- For API clients (Homepage, etc.), use Basic Auth with your actual password (not the hash)
- The hash is Base64-encoded to prevent Docker Compose from interpreting
$characters as variables
Web Interface Settings
Access the web interface at http://localhost:7676/ (or your server IP) to configure:
Schedule Settings:
- Frequency: Daily, Weekly, or Monthly
- Time: When to run the cleanup (supports both 12h and 24h format)
- Day: Day of week (for weekly) or day of month (for monthly)
Cleanup Options:
- ☑️ All unused containers
- ☑️ All unused images
- ☑️ All unused networks
- ☑️ All unused volumes
**Noti
