Tao
Tao

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.

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.

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, like ubuntu:22.04 or nginx: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.

The main command is docker image rm, or docker rmi for short.

bash

# Delete a single image
docker rmi redis:latest

# Delete multiple images
docker rmi redis:latest nginx:stable alpine:3.18

bash

# Using short ID
docker rmi eeae25ada2aa

bash

docker rmi my-registry/my-repo@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf

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.

  1. Find the dependent containers

bash

# View all containers
docker ps -a

# Find containers for a specific image
docker ps -a --filter "ancestor=nginx:latest"
  1. Stop running containers

bash

docker stop <container_id_or_name>
  1. Delete containers

bash

docker rm <container_id_or_name>
  1. Try deleting the image again

bash

docker rmi <image_name>

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.

The -f or --force flag can bypass certain safety checks, but use it carefully.

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.

bash

# 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

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.

Modern applications often need to support multiple CPU architectures (like amd64 and arm64).

bash

# Delete only the specific platform image
docker image rm --platform=linux/arm64 my-app:latest

“Dangling” images are image layers that have no tags and aren’t referenced by containers.

bash

# Clean up dangling images (will prompt for confirmation)
docker image prune

# Skip confirmation
docker image prune -f

“Unused” images are images not associated with any containers.

bash

# 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.

docker system prune is the most comprehensive cleanup tool.

bash

docker system prune

Cleans up:

  • All stopped containers
  • All unused networks
  • All dangling images
  • All build cache

bash

docker system prune -a

Additionally cleans up all unused images.

bash

docker system prune -a --volumes

Extremely dangerous: Also deletes all unused volumes, which could cause data loss.

For more detailed information about Docker prune commands, check out: Docker Prune Complete Guide

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

For developers (local machines):

  • Prevent accumulation: Use the --rm flag with docker 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 use docker 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.

  1. Understand dependencies: Delete containers first, then images
  2. Choose the right tool: From precise docker image rm to broad docker system prune
  3. Match your environment: Be aggressive in dev, conservative in production
  4. Use filters: Get precise control instead of blind deletion
  5. Build a strategy: Use tags and time filters for automated cleanup

Related Content