Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
  • Privacy Policy
Docker

Docker: Clean Up Disk Space by Removing Unused Images and Containers

- 03.02.26 - ErcanOPAK

Docker eating 50GB of disk space? Old images, stopped containers, and dangling volumes pile up fast. One command reclaims it all.

Check Current Disk Usage:

docker system df

# Output:
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          47        12        28.5GB    18.2GB (63%)
Containers      89        5         10.2GB    9.8GB (96%)
Local Volumes   23        8         2.3GB     1.1GB (47%)
Build Cache     0         0         0B        0B

# 29.1GB can be reclaimed!

The Nuclear Option – Clean Everything:

docker system prune -a --volumes

# Removes:
# - All stopped containers
# - All networks not used by at least one container
# - All images without at least one container
# - All build cache
# - All unused volumes

# Typical result: 20-40GB freed

⚠️ Warning: This removes ALL unused images, even ones you might want to keep!

Safer: Clean Selectively

# Remove stopped containers only
docker container prune

# Remove dangling images (untagged, :)
docker image prune

# Remove unused images (not used by any container)
docker image prune -a

# Remove unused volumes
docker volume prune

# Remove unused networks
docker network prune

Remove Specific Old Images:

# List images by size
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | sort -k3 -h

# Remove specific image
docker rmi image-name:tag

# Remove all images older than 30 days
docker images --format "{{.ID}} {{.CreatedAt}}" | \
  awk '$2 < "2024-12-01" {print $1}' | \
  xargs docker rmi

Auto-Delete Containers on Exit:

# Add --rm flag when running containers
docker run --rm -it ubuntu bash

# Container auto-deletes when you exit
# No leftover stopped containers

Clean Build Cache:

# Build cache can be 10-20GB!
docker builder prune

# Or clear everything including cache
docker builder prune -a

Why Disk Fills Up:

Typical development workflow:
1. Pull image: nginx:latest (200MB)
2. Build custom image: my-app:v1 (500MB)
3. Test, make changes
4. Build again: my-app:v2 (500MB)
5. Repeat 10 times = 10 versions

Result after 1 week:
- 10 versions of my-app (5GB)
- Each has 3-5 layers (15GB more)
- Old nginx base images (2GB)
- Stopped test containers (1GB)
Total: 23GB just from one app!

Automated Cleanup - Cron Job:

# Add to crontab
crontab -e

# Run daily cleanup at 3 AM
0 3 * * * docker system prune -f

# -f flag skips confirmation prompt

Keep Recent Images, Delete Old:

# Keep only last 5 versions of each image
for image in $(docker images --format "{{.Repository}}" | sort -u); do
    docker images $image --format "{{.ID}}" | tail -n +6 | xargs docker rmi -f
done

# Keeps 5 most recent, deletes older

Volume Cleanup (Careful!):

# List volumes and their size
docker system df -v

# Remove specific unused volume
docker volume rm volume-name

# ⚠️ DANGER: Remove ALL unused volumes
docker volume prune
# This deletes database data if container is stopped!

Production Best Practices:

# Safe cleanup for production:
# 1. Remove stopped containers (safe)
docker container prune -f

# 2. Remove dangling images only (safe)
docker image prune -f

# 3. DO NOT prune volumes in production!
# Might delete database data

# 4. Keep at least 2-3 versions of each image
# For rollback capability

Monitor Disk Space:

# Weekly report script
#!/bin/bash
echo "Docker Disk Usage Report"
echo "========================"
docker system df
echo ""
echo "Top 10 Largest Images:"
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | \
  sort -k3 -h | tail -10

Related posts:

Docker Containers Work Locally but Fail in CI

Multi-Stage Builds = Smaller Images

Docker Images Grow Over Time Without Reason

Post Views: 4

Post navigation

Kubernetes: Force Delete Stuck Pods in Terminating State Instantly
AI Prompt: Diagnose Home Repair Issues with Photos and Get Step-by-Step Fix Instructions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

March 2026
M T W T F S S
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
« Feb    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (938)
  • How to add default value for Entity Framework migrations for DateTime and Bool (836)
  • Get the First and Last Word from a String or Sentence in SQL (828)
  • How to select distinct rows in a datatable in C# (801)
  • How to make theater mode the default for Youtube (736)
  • Add Constraint to SQL Table to ensure email contains @ (575)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (554)
  • Average of all values in a column that are not zero in SQL (523)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (477)
  • Find numbers with more than two decimal places in SQL (441)

Recent Posts

  • C#: Saving Memory with yield return (Lazy Streams)
  • C#: Why Records are Better Than Classes for Data DTOs
  • C#: Creating Strings Without Memory Pressure with String.Create
  • SQL: Protecting Sensitive Data with Dynamic Data Masking
  • SQL: Writing Readable Queries with Common Table Expressions (CTE)
  • .NET Core: Handling Errors Gracefully with Middleware
  • .NET Core: Mastering Service Lifetimes (A Visual Guide)
  • Git: Surgical Stashing – Don’t Save Everything!
  • Git: Writing Commits That Your Future Self Won’t Hate
  • Ajax: Improving Perceived Speed with Skeleton Screens

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (938)
  • How to add default value for Entity Framework migrations for DateTime and Bool (836)
  • Get the First and Last Word from a String or Sentence in SQL (828)
  • How to select distinct rows in a datatable in C# (801)
  • How to make theater mode the default for Youtube (736)

Recent Posts

  • C#: Saving Memory with yield return (Lazy Streams)
  • C#: Why Records are Better Than Classes for Data DTOs
  • C#: Creating Strings Without Memory Pressure with String.Create
  • SQL: Protecting Sensitive Data with Dynamic Data Masking
  • SQL: Writing Readable Queries with Common Table Expressions (CTE)

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com