Docker: How to Remove Images, Containers, and Volumes
Docker containers and images accumulate quickly. Your system fills with unused images, stopped containers, and orphaned volumes. Disk space gets eaten. Cleanup becomes necessary.
But cleanup can be tricky. Remove the wrong thing, and you break your pipeline. Delete an image someone depends on, and now your deployment fails.
This guide shows you exactly how to clean up Docker safely, from basic commands to production-grade strategies.
Understanding Docker Storage Layers
Before cleanup, understand what Docker stores:
Images : The templates. Each image is immutable and can be used to start multiple containers.
Containers : Running (or stopped) instances of images. Each container has a writable layer on top of the image.
Volumes : Persistent data storage. Separate from images and containers.
Build cache : Intermediate layers from docker build, used to speed up rebuilds.
Cleanup must respect dependencies. You can't delete an image if a container depends on it (even a stopped container).
Removing Docker Images
List Images
First, see what you have:
docker images
Output shows: REPOSITORY, TAG, IMAGE ID, SIZE, and creation date.
To list only dangling images (images with no tags, typically orphaned):
docker images -f "dangling=true"
Remove Specific Images
Remove a single image by name or ID:
docker rmi image_name:tag
Or by image ID:
docker rmi abc123def456
Remove multiple images at once:
docker rmi image1:tag1 image2:tag2 image3:tag3
If a container (even stopped) uses the image, you must stop and remove the container first:
docker rm container_id
docker rmi image_id
To force removal (aggressive, not recommended in production):
docker rmi -f image_id
Remove All Dangling Images
Dangling images are orphaned images left behind by failed builds or updates:
docker image prune
Confirm when prompted. This is safe: dangling images aren't used by anything.
To force without confirmation:
docker image prune -f
Remove all unused images (including those not referenced by any container):
docker image prune -a
This is more aggressive. Use it when you know you want to clean up thoroughly.
Removing Docker Containers
List Containers
View all containers (running and stopped):
docker ps -a
View only running containers:
docker ps
Remove Specific Containers
Remove a stopped container:
docker rm container_id
Remove by name:
docker rm container_name
If the container is still running, stop it first:
docker stop container_id
docker rm container_id
Or combine stop and remove:
docker rm -f container_id
Remove All Stopped Containers
docker container prune
This removes all stopped containers. Running containers are safe.
Confirm when prompted, or force with:
docker container prune -f
Removing Docker Volumes
Volumes persist independently. A volume can outlive the container that created it.
List Volumes
docker volume ls
Find dangling volumes (not in use by any container):
docker volume ls -f "dangling=true"
Remove Specific Volumes
docker volume rm volume_name
Remove by name:
docker volume rm my_app_data
Remove multiple volumes:
docker volume rm vol1 vol2 vol3
Remove All Dangling Volumes
docker volume prune
Confirm when prompted. This removes volumes not used by any container.
Force without confirmation:
docker volume prune -f
Complete Cleanup: Docker System Prune
The nuclear option (but safe for dangling objects):
docker system prune
This removes in one command:
- All stopped containers
- All dangling images
- All dangling volumes
- All unused networks
Force without confirmation:
docker system prune -f
To also remove all unused images (not just dangling):
docker system prune -a
To remove volumes as well:
docker system prune -a --volumes
This removes:
- All stopped containers
- All unused images
- All unused volumes
- All unused networks
Use this when you want a complete cleanup. It's safe as long as you have no stopped containers or images you plan to reuse.
Modern Docker Best Practices: Build Optimization
Cleanup becomes less necessary if you build smaller images in the first place.
Multi-Stage Builds
Multi-stage builds dramatically reduce final image size:
# Build stage
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .
# Final stage - tiny runtime image
FROM alpine:latest
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]
The builder stage's dependencies (Go compiler, build tools) don't make it into the final image. Final size: often 10-50MB instead of 500MB+.
Dockerfile Best Practices
Order layers from least-changing to most-changing:
FROM ubuntu:22.04
# Base dependencies (rarely change)
RUN apt-get update && apt-get install -y curl jq
# Application dependencies (change occasionally)
COPY requirements.txt .
RUN pip install -r requirements.txt
# Source code (changes frequently)
COPY . .
ENTRYPOINT ["python", "app.py"]
Docker caches layers. If you change source code, Docker only rebuilds from that layer onward. Expensive dependencies are already cached.
Use smaller base images:
| Base Image | Size |
|---|---|
| ubuntu:22.04 | 77 MB |
| debian:12-slim | 28 MB |
| alpine:latest | 7 MB |
| scratch | 0 MB (for static binaries) |
Alpine can create images 10x smaller than Ubuntu.
Build Cache Cleanup
The docker build system maintains cache layers. Prune stale build cache:
docker builder prune
Remove all build cache:
docker builder prune -a
Docker Cleanup in Production: Kubernetes/Hikube
If you run Docker in production via Kubernetes (like Hikube.cloud), container management is different.
Container Lifecycle in Kubernetes
Kubernetes automatically removes containers when pods are deleted. You don't manually remove containers.
However, old images accumulate on nodes. Kubernetes has built-in garbage collection:
# Images are collected when:
# - unused for more than 5 minutes (configurable)
# - AND node disk usage > threshold (usually 85%)
Image Cleanup Strategy for Kubernetes
1. Use specific image tags, not latest:
# Good: explicit version
image: myapp:v1.2.3
# Avoid: 'latest' tag masks old images
image: myapp:latest
Specific tags prevent accidental rollbacks to old versions and help with garbage collection.
2. Set appropriate imagePullPolicy:
# For images from your private registry
imagePullPolicy: IfNotPresent # Use local copy if it exists
# For images you update frequently
imagePullPolicy: Always # Always fetch fresh version
3. Use image lifecycle hooks for cleanup:
For self-hosted clusters, implement image pruning:
# On each node, periodically:
docker image prune -a --filter "until=72h" -f
This removes images unused for 3+ days.
4. Limit image retention in your registry:
In your container registry (Docker Hub, ECR, Harbor, etc.), set automatic cleanup policies:
# Example Harbor cleanup rule:
Pattern: "*"
Keep the recent: 10 # Keep only last 10 images per repository
Hikube Considerations
If you use Hikube (Hidora's managed Kubernetes):
- Node storage is managed automatically
- Garbage collection runs on all nodes
- Image cleanup respects your deployment requirements
- No manual intervention needed
Hikube handles image cleanup as part of the managed service, letting you focus on application deployments.
Cleanup Automation
Manual cleanup gets forgotten. Automate it:
Docker System Prune via Cron
Create a cleanup script:
#!/bin/bash
# /usr/local/bin/docker-cleanup.sh
docker system prune -a --volumes -f
echo "Docker cleanup completed at $(date)" >> /var/log/docker-cleanup.log
Make it executable:
chmod +x /usr/local/bin/docker-cleanup.sh
Add to crontab (run weekly):
crontab -e
# Add line:
0 2 * * 0 /usr/local/bin/docker-cleanup.sh
CI/CD Pipeline Cleanup
In your GitHub Actions or GitLab CI, add image cleanup:
# GitHub Actions example
- name: Clean up Docker images
run: docker image prune -a -f --filter "until=720h"
This runs after deployments, keeping recent images but removing old ones.
Safe Cleanup Checklist
Before running cleanup commands:
- Verify which images/containers/volumes will be removed
- List them first (without -f flag)
- Confirm no running containers depend on those resources
- Check if any container is stopped but planned for restart
- Verify volumes contain no important data
- Have backups of stateful data if needed
- Run on a non-critical system first
- Document what you're cleaning up (for audit purposes)
The Bottom Line
Docker cleanup is straightforward once you understand the dependencies:
- Remove images you don't use : docker image prune
- Remove stopped containers : docker container prune
- Remove unused volumes : docker volume prune
- Or do everything at once : docker system prune
For production, prefer:
- Multi-stage builds to keep images small
- Specific tags instead of 'latest'
- Kubernetes garbage collection (automatic)
- Automated cleanup schedules
In managed Kubernetes environments like Hikube, image cleanup is handled automatically, letting your team focus on application development rather than infrastructure maintenance.
Related Reading
Running Docker in production? Hidora's Hikube platform manages image lifecycle, garbage collection, and infrastructure complexity: Managed Kubernetes (Hikube) · Technical Consultation



