Automate Docker Pruning with Daily Cron Jobs

by Alex Gallacher (16 months ago • 6 min read) Counting views…
docker automation devops server-management
Set up automated Docker maintenance with cron jobs to prune unused images, volumes and networks. Prevent disk space issues on your VPS with this simple automation guide.
A docker whale illustration being swept clean to represent automated pruning

Introduction

Running Docker containers in production means dealing with accumulated images, orphaned volumes, and unused networks. If not kept in check, these can quickly eat up disk space and cause issues on your server.

To prevent this, we’ll set up a simple daily cleanup routine using cron jobs to automatically prune unused Docker resources.

This post is for engineers who are familiar with Docker and want a straightforward automation solution.

Table of Contents

Docker Prune Basics

Docker has a fantastic prune command to clean up all unused Docker containers, networks and volumes.

Using Watchtower? If you’re using Watchtower, the removal of old images and volumes can be achieved with additional arguments on the container. See the official documentation for details.

Let’s check out the basic prune command:

Basic Docker Prune Command
docker system prune

Just a word of warning: This command will delete dangling and unused images (unused images are images no longer referenced by any containers), networks that are not used, the build cache, and any stopped containers you might have.

Terminal output showing the docker system prune command being run

Including Volume Cleanup

If you also want to prune unused volumes (use with some degree of caution1), you can append --volumes to the same command:

Prune with Volumes (Use with Caution)
docker system prune --volumes

If this is the first time you’ve run this command, you may have a few gigs of data that gets reclaimed. For me this was 0B since I had previously run the command.

I’m all for saving time, so let’s automate this command.

Setting Up Daily Automation

To automate this process, the simplest way is to run a cron job daily to execute our prune command with a filter to delete images that are over a certain age.

Automated Prune Command with Age Filter
docker system prune -af --filter "until=$((30*24))h"

Breaking Down the Command

Let’s break this command down so you can see what it’s doing:

Command Breakdown
docker system prune -af --filter "until=$((30*24))h"
# ↑ ↑ ↑ ↑
# │ │ │ └─ Age filter (30 days)
# │ │ └─ Force (no prompt)
# │ └─ All unused images
# └─ Base prune command

Flag explanations:

  • docker system prune: Instructs Docker to prune unused containers
  • -af: We’ve combined two flags here:
    • -a: Forces Docker to look for all containers that are not in use anymore
    • -f: Prevents the confirmation prompt
  • --filter "until=$((30*24))h": Specifies the age of images to delete (images older than 30 days). We’re using some basic maths logic in bash here as bash only supports h (Hours). So let’s calculate 30*24 hours which gives us 1 month in hours. You can shorten this time should you have very limited disk space on your VPS.

Be careful with using the -a flag as this refers to images not referenced by any current containers - this is highly destructive.

Creating the Cron Job

Let’s create a new file in the cron directory to house our command:

Create Cron Job File
sudo nano /etc/cron.daily/docker-prune

Once the file opens, add the prune command we created earlier and inform the OS it’s a bash file with #!/bin/bash:

/etc/cron.daily/docker-prune
#!/bin/bash
docker system prune -af --filter "until=$((30*24))h"

Save and close the file (hit Ctrl + O and then Ctrl + X to save and close the file if using Nano), then run the following chmod command to make it executable:

Make Script Executable
sudo chmod +x /etc/cron.daily/docker-prune

Testing the Setup

Docker will now execute this command daily2. To test the daily cron register, you can run:

Test Cron Job Execution
sudo run-parts /etc/cron.daily

If you see the following output, it means the command ran successfully as part of the cron daily register:

Terminal output showing the daily cron job execution results

Advanced Configuration

If you want to add logging to track what’s being cleaned up, you can enhance the script:

Enhanced Docker Cleanup Script with Logging
#!/bin/bash
LOG_FILE="/var/log/docker-cleanup.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] Starting Docker cleanup..." >> "$LOG_FILE"
docker system prune -af --filter "until=$((30*24))h" >> "$LOG_FILE" 2>&1
echo "[$DATE] Docker cleanup completed" >> "$LOG_FILE"

Troubleshooting

If your cron job isn’t working, here are some common issues:

Permission Issues

Permission denied: Make sure the script has execute permissions:

Fix Permission Issues
sudo chmod +x /etc/cron.daily/docker-prune

Service Issues

Cron not running: Check if the cron service is active:

Check Cron Service
sudo systemctl status cron

Script Testing

Script errors: Test the script manually first:

Test Script Manually
sudo /etc/cron.daily/docker-prune

Resources

If you have other resources, please reach out and I’ll add them here.

Footnotes

  1. Volume Pruning Warning: The --volumes flag permanently removes volume data that might contain important application data, databases, or configuration files. Always implement a backup strategy before enabling automated volume pruning. Use docker volume ls to review volumes before deletion.

  2. Docker’s pruning mechanism includes built-in safety measures - it will never remove images that are being used by any containers (running or stopped), making it safe for automation in production environments.