How to clean up unused Docker images in Linux

How to Clean Up Unused Docker Images in Linux Docker has revolutionized containerization technology, making it easier than ever to deploy and manage applications. However, as you work with Docker over time, your system can accumulate numerous unused images, containers, volumes, and networks that consume valuable disk space. This comprehensive guide will teach you everything you need to know about cleaning up unused Docker images in Linux, from basic commands to advanced automation strategies. Table of Contents - [Introduction](#introduction) - [Prerequisites](#prerequisites) - [Understanding Docker Storage](#understanding-docker-storage) - [Basic Docker Cleanup Commands](#basic-docker-cleanup-commands) - [Advanced Cleanup Strategies](#advanced-cleanup-strategies) - [Automated Cleanup Solutions](#automated-cleanup-solutions) - [Monitoring Docker Storage Usage](#monitoring-docker-storage-usage) - [Troubleshooting Common Issues](#troubleshooting-common-issues) - [Best Practices](#best-practices) - [Conclusion](#conclusion) Introduction Docker images can quickly accumulate on your Linux system, especially in development environments where you frequently pull, build, and test different images. These unused images, also known as "dangling" images, can consume gigabytes of disk space and impact system performance. Regular cleanup of unused Docker images is essential for maintaining an efficient Docker environment. This guide covers multiple approaches to Docker image cleanup, from simple one-line commands to sophisticated automated solutions. You'll learn how to identify unused images, safely remove them, and implement preventive measures to keep your Docker environment clean and optimized. Prerequisites Before proceeding with Docker image cleanup, ensure you have: System Requirements - Linux operating system (Ubuntu, CentOS, RHEL, Debian, or similar) - Docker installed and running - Sufficient user privileges (sudo access or Docker group membership) - Basic command-line knowledge Checking Docker Installation Verify your Docker installation with: ```bash docker --version docker info ``` User Permissions Ensure your user can execute Docker commands without sudo: ```bash sudo usermod -aG docker $USER ``` Note: You may need to log out and back in for group changes to take effect. Understanding Docker Storage Docker Storage Architecture Docker uses a layered filesystem approach where images consist of multiple read-only layers. Understanding this architecture helps you make informed decisions about cleanup: - Base layers: Fundamental OS layers shared across images - Application layers: Specific to individual applications - Dangling images: Untagged images no longer referenced by any container - Intermediate images: Created during build processes Checking Current Storage Usage Before cleaning up, assess your current Docker storage usage: ```bash Check overall Docker system usage docker system df Detailed breakdown of space usage docker system df -v List all images with sizes docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}" ``` The `docker system df` command provides output similar to: ``` TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 15 5 2.1GB 1.2GB (57%) Containers 8 2 125MB 100MB (80%) Local Volumes 3 1 50MB 25MB (50%) Build Cache 0 0 0B 0B ``` Basic Docker Cleanup Commands Removing Dangling Images Dangling images are untagged images that are no longer referenced by any container. These are safe to remove: ```bash List dangling images docker images --filter "dangling=true" Remove all dangling images docker image prune Remove dangling images without confirmation prompt docker image prune -f ``` Removing Unused Images Remove all images not currently used by any container: ```bash Remove all unused images (not just dangling) docker image prune -a Remove unused images without confirmation docker image prune -a -f ``` Removing Specific Images Remove individual images by name or ID: ```bash Remove by image name and tag docker rmi nginx:latest Remove by image ID docker rmi 1a2b3c4d5e6f Force remove (even if containers are using the image) docker rmi -f nginx:latest Remove multiple images docker rmi nginx:latest ubuntu:18.04 alpine:3.12 ``` Comprehensive System Cleanup Remove all unused Docker objects (images, containers, volumes, networks): ```bash Remove all unused objects docker system prune Remove everything including unused images docker system prune -a Remove everything without confirmation docker system prune -a -f Remove everything including volumes docker system prune -a --volumes -f ``` Advanced Cleanup Strategies Time-Based Cleanup Remove images older than a specific timeframe: ```bash Remove images created more than 24 hours ago docker image prune -a --filter "until=24h" Remove images older than 7 days docker image prune -a --filter "until=168h" Remove images created before a specific date docker image prune -a --filter "until=2024-01-01T00:00:00" ``` Size-Based Cleanup Target large images for removal: ```bash List images sorted by size (largest first) docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | sort -k3 -hr Create a script to remove images larger than 1GB #!/bin/bash docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | \ grep -E '[0-9]+(\.[0-9]+)?GB' | \ while read image size; do echo "Removing large image: $image ($size)" docker rmi "$image" done ``` Label-Based Cleanup Use labels to organize and clean up images: ```bash Remove images with specific labels docker image prune --filter "label=environment=development" Remove images without specific labels docker image prune --filter "label!=environment=production" ``` Pattern-Based Removal Remove images matching specific patterns: ```bash Remove all images from a specific registry docker images | grep "myregistry.com" | awk '{print $3}' | xargs docker rmi Remove images with specific naming pattern docker images | grep "temp-" | awk '{print $1":"$2}' | xargs docker rmi Remove all untagged images docker images | grep "" | awk '{print $3}' | xargs docker rmi ``` Automated Cleanup Solutions Creating Cleanup Scripts Basic Cleanup Script Create a comprehensive cleanup script: ```bash #!/bin/bash docker-cleanup.sh set -e echo "Starting Docker cleanup..." Remove stopped containers echo "Removing stopped containers..." docker container prune -f Remove dangling images echo "Removing dangling images..." docker image prune -f Remove unused images older than 7 days echo "Removing unused images older than 7 days..." docker image prune -a -f --filter "until=168h" Remove unused volumes echo "Removing unused volumes..." docker volume prune -f Remove unused networks echo "Removing unused networks..." docker network prune -f Show remaining usage echo "Current Docker disk usage:" docker system df echo "Docker cleanup completed!" ``` Make the script executable: ```bash chmod +x docker-cleanup.sh ``` Advanced Cleanup Script with Logging ```bash #!/bin/bash advanced-docker-cleanup.sh LOGFILE="/var/log/docker-cleanup.log" RETENTION_DAYS=7 MIN_FREE_SPACE_GB=5 log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOGFILE" } check_free_space() { local free_space_gb=$(df /var/lib/docker | awk 'NR==2 {print int($4/1024/1024)}') echo $free_space_gb } log_message "Starting Docker cleanup process" Check available space before cleanup SPACE_BEFORE=$(check_free_space) log_message "Free space before cleanup: ${SPACE_BEFORE}GB" Perform cleanup operations log_message "Removing stopped containers..." REMOVED_CONTAINERS=$(docker container prune -f 2>&1 | grep "Total reclaimed space" || echo "0B") log_message "Containers cleanup result: $REMOVED_CONTAINERS" log_message "Removing dangling images..." REMOVED_IMAGES=$(docker image prune -f 2>&1 | grep "Total reclaimed space" || echo "0B") log_message "Dangling images cleanup result: $REMOVED_IMAGES" log_message "Removing unused images older than ${RETENTION_DAYS} days..." REMOVED_OLD_IMAGES=$(docker image prune -a -f --filter "until=${RETENTION_DAYS}d" 2>&1 | grep "Total reclaimed space" || echo "0B") log_message "Old images cleanup result: $REMOVED_OLD_IMAGES" Check space after cleanup SPACE_AFTER=$(check_free_space) SPACE_FREED=$((SPACE_AFTER - SPACE_BEFORE)) log_message "Free space after cleanup: ${SPACE_AFTER}GB (freed: ${SPACE_FREED}GB)" Alert if still low on space if [ $SPACE_AFTER -lt $MIN_FREE_SPACE_GB ]; then log_message "WARNING: Still low on disk space (${SPACE_AFTER}GB remaining)" fi log_message "Docker cleanup process completed" ``` Cron Job Automation Automate cleanup with cron jobs: ```bash Edit crontab crontab -e Add entries for automated cleanup Daily cleanup at 2 AM 0 2 * /path/to/docker-cleanup.sh >> /var/log/docker-cleanup.log 2>&1 Weekly comprehensive cleanup on Sundays at 3 AM 0 3 0 /path/to/advanced-docker-cleanup.sh Hourly dangling image cleanup during business hours 0 9-17 1-5 docker image prune -f >> /var/log/docker-cleanup.log 2>&1 ``` Systemd Service for Cleanup Create a systemd service for regular cleanup: ```bash Create service file sudo nano /etc/systemd/system/docker-cleanup.service ``` Service file content: ```ini [Unit] Description=Docker Cleanup Service Requires=docker.service After=docker.service [Service] Type=oneshot ExecStart=/usr/local/bin/docker-cleanup.sh User=root StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target ``` Create timer file: ```bash sudo nano /etc/systemd/system/docker-cleanup.timer ``` Timer file content: ```ini [Unit] Description=Run Docker Cleanup Daily Requires=docker-cleanup.service [Timer] OnCalendar=daily Persistent=true [Install] WantedBy=timers.target ``` Enable and start the timer: ```bash sudo systemctl daemon-reload sudo systemctl enable docker-cleanup.timer sudo systemctl start docker-cleanup.timer ``` Monitoring Docker Storage Usage Real-Time Monitoring Monitor Docker storage usage in real-time: ```bash Watch Docker system usage watch -n 30 'docker system df' Monitor specific directory sizes watch -n 60 'du -sh /var/lib/docker/overlay2' Custom monitoring script #!/bin/bash while true; do clear echo "=== Docker Storage Monitor ===" echo "Timestamp: $(date)" echo docker system df echo echo "=== Top 10 Largest Images ===" docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | head -11 sleep 60 done ``` Setting Up Alerts Create alerting for low disk space: ```bash #!/bin/bash docker-space-alert.sh THRESHOLD_GB=10 EMAIL="admin@example.com" AVAILABLE_SPACE=$(df /var/lib/docker | awk 'NR==2 {print int($4/1024/1024)}') if [ $AVAILABLE_SPACE -lt $THRESHOLD_GB ]; then MESSAGE="WARNING: Docker storage space is running low. Only ${AVAILABLE_SPACE}GB remaining." echo "$MESSAGE" | mail -s "Docker Storage Alert" "$EMAIL" logger "$MESSAGE" fi ``` Prometheus Monitoring For advanced monitoring, integrate with Prometheus: ```yaml docker-compose.yml for monitoring stack version: '3.7' services: node-exporter: image: prom/node-exporter:latest ports: - "9100:9100" volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)' ``` Troubleshooting Common Issues Image in Use Errors When encountering "image is being used by running container" errors: ```bash List containers using the image docker ps -a --filter ancestor=IMAGE_NAME Stop and remove containers first docker stop $(docker ps -q --filter ancestor=IMAGE_NAME) docker rm $(docker ps -aq --filter ancestor=IMAGE_NAME) Then remove the image docker rmi IMAGE_NAME ``` Permission Denied Errors Fix permission issues: ```bash Add user to docker group sudo usermod -aG docker $USER Change ownership of Docker socket (temporary fix) sudo chmod 666 /var/run/docker.sock Restart Docker service sudo systemctl restart docker ``` Storage Driver Issues Handle storage driver problems: ```bash Check current storage driver docker info | grep "Storage Driver" Clean up overlay2 storage sudo systemctl stop docker sudo rm -rf /var/lib/docker/overlay2/* sudo systemctl start docker Rebuild images if necessary docker pull IMAGE_NAME ``` Network-Related Cleanup Issues Resolve network cleanup problems: ```bash Force remove networks docker network rm $(docker network ls -q) Remove networks not used by containers docker network prune -f Reset Docker networking sudo systemctl stop docker sudo ip link delete docker0 sudo systemctl start docker ``` Recovery from Failed Cleanup Recover from cleanup operations gone wrong: ```bash Check Docker daemon status sudo systemctl status docker Restart Docker daemon sudo systemctl restart docker Verify image integrity docker images --digests Re-pull critical images docker pull nginx:latest docker pull ubuntu:20.04 ``` Best Practices Development Environment Practices 1. Regular Cleanup Schedule: Implement daily or weekly cleanup routines 2. Use Multi-stage Builds: Reduce final image sizes 3. Leverage .dockerignore: Exclude unnecessary files from build context 4. Tag Images Appropriately: Use meaningful tags for better organization ```dockerfile Multi-stage build example FROM node:16-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production FROM node:16-alpine AS runtime WORKDIR /app COPY --from=builder /app/node_modules ./node_modules COPY . . EXPOSE 3000 CMD ["npm", "start"] ``` Production Environment Practices 1. Automated Cleanup: Use systemd timers or cron jobs 2. Monitoring Integration: Set up alerts for storage usage 3. Selective Cleanup: Preserve production images while cleaning development artifacts 4. Backup Strategy: Ensure critical images are backed up before cleanup Storage Optimization Techniques 1. Image Layer Optimization: ```dockerfile Bad: Creates multiple layers RUN apt-get update RUN apt-get install -y package1 RUN apt-get install -y package2 Good: Single layer RUN apt-get update && \ apt-get install -y package1 package2 && \ rm -rf /var/lib/apt/lists/* ``` 2. Use Alpine-based Images: ```bash Instead of ubuntu:latest (72MB) FROM alpine:3.15 # 5.6MB Install packages RUN apk add --no-cache package-name ``` 3. Implement Build Cache Strategies: ```bash Use BuildKit for better caching export DOCKER_BUILDKIT=1 docker build --cache-from myapp:cache . ``` Security Considerations 1. Scan Images Before Cleanup: Ensure you're not removing security-patched versions 2. Maintain Image Inventory: Keep track of which images are in use 3. Implement Access Controls: Restrict who can perform cleanup operations ```bash Scan images for vulnerabilities docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ -v $HOME/Library/Caches:/root/.cache/ \ aquasec/trivy image nginx:latest ``` Performance Optimization 1. Parallel Cleanup Operations: ```bash Remove multiple images in parallel echo "image1 image2 image3" | xargs -n 1 -P 3 docker rmi ``` 2. Optimize Cleanup Timing: Run cleanup during low-usage periods 3. Use Filters Efficiently: Target specific images rather than broad cleanup Conclusion Effective Docker image cleanup is crucial for maintaining a healthy Linux system. This comprehensive guide has covered everything from basic cleanup commands to advanced automation strategies. Key takeaways include: - Regular Maintenance: Implement automated cleanup schedules to prevent storage issues - Selective Cleanup: Use filters and targeted approaches rather than broad cleanup operations - Monitoring: Keep track of storage usage and set up alerts for proactive management - Best Practices: Follow development and production guidelines for optimal Docker usage Next Steps 1. Implement Basic Cleanup: Start with simple `docker system prune` commands 2. Create Automation: Set up cron jobs or systemd timers for regular cleanup 3. Add Monitoring: Implement storage monitoring and alerting 4. Optimize Images: Review and optimize your Docker images for better space efficiency 5. Document Procedures: Create runbooks for your team's cleanup procedures Additional Resources - Docker Documentation: Official Docker cleanup guides - Container Best Practices: Industry standards for container management - Monitoring Tools: Prometheus, Grafana, and other monitoring solutions - Security Scanning: Tools like Trivy, Clair, and Anchore for image security By following this guide and implementing these practices, you'll maintain a clean, efficient Docker environment that performs optimally while conserving valuable disk space. Remember to always test cleanup procedures in development environments before applying them to production systems, and maintain regular backups of critical images and data. Regular Docker maintenance is not just about freeing up disk space—it's about maintaining system performance, security, and operational efficiency. Make Docker cleanup a standard part of your Linux system administration routine, and your infrastructure will thank you for it.