Complete Guide to Deleting Docker Images and System Cleanup
Managing Docker images is part of everyday work for Docker operations teams. As images pile up, they eat up a lot of disk space. While deleting an image with a single command is pretty simple, operations folks need to understand what’s happening under the hood with Docker. This guide covers the commands and best practices for deleting Docker images, plus explains how Docker images work, so you can better understand the technology.
Docker Image Basics
Docker Image Structure
A Docker image isn’t just one big file. It’s a lightweight, standalone, executable package that contains everything needed to run an application: code, runtime, system tools, system libraries, and settings. This package is made up of a series of read-only layers, where each layer represents a specific instruction from the image’s Dockerfile. This layered approach is what makes Docker so efficient - layers can be shared between different images, which cuts down on storage space and speeds up builds and pulls.
How Docker Images Are Identified
Image ID
- A unique identifier that’s a SHA256 hash based on the image configuration and layers
- Example:
eeae25ada2aa
Tags
- Human-readable labels that point to image IDs
- Format:
repository:tag
, likeubuntu:22.04
ornginx:latest
- One image ID can have multiple tags
Digest
- SHA256 hash of the image manifest file
- Immutable, guarantees you’re referencing the exact same image version every time
Understanding the difference between these identifiers is crucial. A tag is a movable pointer, while an image ID represents the actual object. When you try to delete an image, you’re usually working with the pointer (tag) first. For example, if an image with ID fd484f19954f has two tags test1:latest and test2:latest, running docker rmi test1:latest won’t delete the underlying image data. It just removes the test1:latest tag. The command output shows this by displaying Untagged: test1:latest. The image layers and ID fd484f19954f stay on the system because they’re still referenced by the test2:latest tag. Only when the last tag pointing to an image ID is removed will Docker try to delete the image layers themselves, which produces a Deleted: sha256:… message in the output. This concept of managing references is the most fundamental principle of Docker image removal.
Docker Image Deletion Commands
The main command is docker image rm
, or docker rmi
for short.
Delete by Tag
# Delete a single image
docker rmi redis:latest
# Delete multiple images
docker rmi redis:latest nginx:stable alpine:3.18
Delete by Image ID
# Using short ID
docker rmi eeae25ada2aa
Delete by Digest
docker rmi my-registry/my-repo@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
Docker Container Dependency Issues
Common error: Error response from daemon: conflict: unable to remove image...: it is being used by one or more containers
This error happens because Docker protects images that are being used by containers, including stopped containers.
How to Fix It
- Find the dependent containers
# View all containers
docker ps -a
# Find containers for a specific image
docker ps -a --filter "ancestor=nginx:latest"
- Stop running containers
docker stop <container_id_or_name>
- Delete containers
docker rm <container_id_or_name>
- Try deleting the image again
docker rmi <image_name>
Force Deleting Docker Images
While Docker’s default deletion process is safe and reliable, sometimes we need to bypass these protection mechanisms. This is especially true when dealing with multi-tag images or multi-platform builds, where we need some advanced parameters. However, you need to understand the risks when using these force deletion features.
Using the –force Flag
The -f
or --force
flag can bypass certain safety checks, but use it carefully.
Scenario 1: Deleting Multi-Tag Docker Images
If an image ID (like fd484f19954f) is referenced by multiple tags (test1:latest, test:latest, test2:latest), trying to remove it by ID without the force flag will cause an error because Docker won’t remove images that still have tags pointing to them. Using docker rmi -f <IMAGE_ID> can override this. It will force untag all related references and then delete the image layers.
# Force delete an image with multiple tags
# This command will untag test1:latest, test:latest, and test2:latest, then delete image fd484f19954f
docker rmi -f fd484f19954f
Scenario 2: Deleting Images Used by Stopped Containers
Important note: docker rmi -f cannot remove an image used by a running container. However, it can be used to remove an image referenced by a stopped container.
When you run docker rmi -f <image_name>
on an image used by a stopped container, it looks like the operation succeeded and the image disappears from the docker images
list. But actually, the image layers haven’t really been deleted from the file system. Since the stopped container still exists, its reference relationship to the parent image layers remains on disk, creating an “orphaned” container state.
Users might think they’ve freed up disk space, but this data is actually still taking up storage. Only when the container itself is explicitly deleted with the docker rm
command will the related image layers actually be cleaned up. This situation can lead to “hidden” disk usage problems and make the system state hard to debug and understand.
Recommendation: Better to delete containers first, then delete images.
Deleting Multi-Platform Images
Modern applications often need to support multiple CPU architectures (like amd64 and arm64).
# Delete only the specific platform image
docker image rm --platform=linux/arm64 my-app:latest
Automated and Bulk Cleanup with Prune
Clean Up Dangling Images
“Dangling” images are image layers that have no tags and aren’t referenced by containers.
# Clean up dangling images (will prompt for confirmation)
docker image prune
# Skip confirmation
docker image prune -f
Clean Up All Unused Images
“Unused” images are images not associated with any containers.
# Clean up all unused images
docker image prune -a
Warning: This will delete all images that don’t have containers associated with them, which could be destructive in CI/CD environments.
System-Level Cleanup
docker system prune
is the most comprehensive cleanup tool.
Default Mode
docker system prune
Cleans up:
- All stopped containers
- All unused networks
- All dangling images
- All build cache
Aggressive Mode
docker system prune -a
Additionally cleans up all unused images.
Dangerous Mode
docker system prune -a --volumes
Extremely dangerous: Also deletes all unused volumes, which could cause data loss.
More Reference Resources
For more detailed information about Docker prune commands, check out: Docker Prune Complete Guide
Best Practices
Docker Image Deletion Command Comparison
Command | Target | Risk Level | Use Case |
---|---|---|---|
docker image rm IMAGE |
Specific image | Low | Delete known unneeded images |
docker image rm -f IMAGE_ID |
Force delete image | Medium | Multi-tag images or images used by stopped containers |
docker image prune |
Dangling images | Low | Regular cleanup, safest option |
docker image prune -a |
All unused images | Medium | Aggressive cleanup on dev machines |
docker system prune |
All dangling resources | Medium-Low | General system cleanup |
docker system prune -a |
All unused resources | High | Use carefully |
docker system prune -a --volumes |
Including volumes | Extremely High | Should almost never be used |
Docker Resource Cleanup Best Practices
For developers (local machines):
-
Prevent accumulation: Use the
--rm
flag withdocker run
for temporary or test containers. This automatically removes containers when they exit, preventing the buildup of stopped containers that hold image references. -
Regular cleanup: Periodically run
docker system prune
to clear dangling images, build cache, and stopped containers. This is a low-risk way to keep your local environment clean. You can also usedocker system prune -a
after confirming there are no important stopped containers or unused images you need to keep.
For CI/CD and shared environments:
-
Prioritize data safety: Never use docker system prune –volumes in any automated scripts or shared environments. The risk of accidental data loss is too high.
-
Use tags for policy enforcement: Implement a tagging strategy for your images. Assign tags for different stages (development, staging, production) or status (keep, archived). Then cleanup jobs can use tag filters like –filter “label!=stage=production” or –filter “label!=keep” to precisely remove resources without touching critical images.
-
Implement retention policies: Use time-based filters like –filter “until=720h” (30 days) in scheduled cleanup jobs to implement rolling retention policies for images and other resources. This prevents unlimited resource consumption in long-running environments.
Summary
- Understand dependencies: Delete containers first, then images
- Choose the right tool: From precise
docker image rm
to broaddocker system prune
- Match your environment: Be aggressive in dev, conservative in production
- Use filters: Get precise control instead of blind deletion
- Build a strategy: Use tags and time filters for automated cleanup