Docker

How to Remove Docker Images Safely and Efficiently

How to Remove Docker Images Safely and Efficiently

Plenty of people type docker rmi -f on a stubborn image and expect it to go away. Sometimes it does. Docker Docs (2026) says -f removes an image used by a running container, yet the Moby daemon source classifies that case as a hard conflict that -f cannot override.

Which command works comes down to the selector you hand it: a tag, an image ID, a digest, or a prune filter. Developers and CI runners lean on docker rmi, docker image rm, docker image prune and docker system prune for this, then check the reclaimable figure in docker system df to see what they got back.

What Is Docker Image Removal?

Removal deletes image tags and any layers nothing else references, and it only touches the local host. Docker Engine frees the disk space. Every remote copy stays exactly where it was.

The CLI exposes this through docker rmi, docker image rm, docker image prune and docker system prune. The first two are aliases of one command.

Tags go first, layers second. If you want the background on what you’re actually deleting, here’s a rundown of the Docker image tag and how it relates to the image itself.

A little vocabulary helps before the commands. A tag is a name:tag label like ubuntu:22.04 that points at an image, and the image ID is the short or long hash that identifies the image underneath it. Pull something by digest and you get a repo@sha256:… reference with no tag at all. A dangling image is an untagged one, shown as <none>:<none>, usually left behind when a rebuild steals the tag. An unused image is any image that no container references, whether that container is running or stopped.

Nothing here reaches the registry. The copy on Docker Hub stays in place, and a later docker pull brings the image back.

How Do Image Layers Determine What Gets Deleted?

A layer is deleted only when no remaining image references it. The OCI image specification describes an image as a stack of read-only layers, each with its own digest, and images built on the same base share those layers on disk.

So if two images share a base and you remove one, you only free the layers unique to it.

Tags vs image ids

One image ID can carry several tags, and every tag is just a pointer.

Why has Docker revolutionized deployment?

Explore Docker statistics: containerization adoption, DevOps transformation, enterprise usage, and how containers changed software delivery.

Discover Docker Insights →

Running docker rmi with a tag removes that tag and nothing more. The image itself goes only when the last tag is gone.

With two tags on one ID, rmi on one of them prints Untagged and the image stays. Remove the last remaining tag and you see Untagged followed by Deleted. Go by ID when several tags exist and Docker refuses, unless you add -f.

Where layer data lives

As of the September 2026 documentation, Docker Engine 29.0 and later uses the containerd image store by default on fresh installations, while upgraded hosts keep the overlay2 storage driver until the store is switched (Docker Docs, 2026).

On overlay2 hosts, shared layers are stored once under /var/lib/docker. On containerd hosts the image data sits in a separate containerd storage path, so a custom Docker data directory won’t move it.

containerd keeps each layer in both compressed and extracted form. The same images therefore take more disk than they would under overlay2.

Paths differ by platform, and this page on where Docker images are stored covers them.

How Do You List Images and Check Disk Usage Before Removing Them?

Run docker image ls to list images and docker system df to see space used and reclaimable. Add -q for ID-only output, –filter dangling=true to preview prune targets, and docker system df -v for per-image shared and unique size.

CommandShowsUse it to
docker image lsRepository, tag, ID, age, sizePick a target
docker image ls -qImage IDs onlyFeed another command
docker image ls –filter dangling=trueUntagged leaf imagesPreview a prune
docker system dfTotal, active, size, reclaimable per typeRecord a baseline
docker system df -vShared and unique size per imageSee what removal frees

Docker’s documented example output for docker system df lists 5 images, 2 of them active, at 16.43 MB in total with 11.63 MB (70%) reclaimable (Docker Docs, 2026).

Look at the RECLAIMABLE column before deleting anything. It’s the quickest sanity check there is.

To find out what’s pinning an image, docker ps -a lists running and stopped containers along with the image each one uses. docker image inspect prints the layer digests of a single image, and docker image history shows how the layers were built and how big each one is.

docker image ls hides intermediate images by default, and dangling images show up as <none>. Add -a if you want the intermediates too.

A Docker command cheat sheet is worth keeping open while you sort out the flags.

How Do You Remove a Single Docker Image?

YouTube player

docker rmi and docker image rm are the same command. Give it a name:tag, a short or long image ID, or a digest. Docker prints Untagged for each tag it removes and Deleted for each layer it drops.

  1. List images with docker image ls and note the tag or ID.
  2. Find containers built from the image with docker ps -a.
  3. Stop and remove those containers.
  4. Run docker rmi name:tag, docker rmi IMAGE\_ID or docker rmi repo@sha256:digest.
  5. Run docker image ls again to confirm the entry is gone.

If a container blocks the removal, stop the container first, then delete it with docker rm.

Read the output carefully. Untagged means Docker removed a tag or digest reference, and the image itself is still there if another tag points at it. Deleted means the layers are actually off the disk.

You can pass several images in one call, like docker image rm IMAGE1 IMAGE2. The –no-prune flag keeps untagged parent images that Docker would otherwise delete along with the child.

The –platform flag removes one platform variant, such as linux/amd64. It needs API 1.50 or later and requires –force, otherwise the command cancels with a warning (Docker Docs, 2026).

How Do You Remove Dangling and Unused Images?

docker image prune deletes dangling images only. docker image prune -a also deletes every image that no container references, and both ask for confirmation unless you add -f.

Both finish with a Total reclaimed space line.

Dangling images only

Dangling images are untagged leaf images, the leftovers of a rebuild that took the tag away.

Run docker image prune and answer y at the prompt. In scripts, docker image prune -f skips the question. If you’d like to see the targets first, docker image ls –filter dangling=true lists them.

The older one-liner, docker rmi $(docker images -f “dangling=true” -q), does the same job and warns when a container uses one of the images.

All unused images

docker image prune -a is the aggressive option.

It removes tagged and untagged images alike, as long as no container references them. Anything a running container uses stays, and so does anything a stopped container uses.

The prompt warns that every image without at least one associated container will go. Add -f to skip it.

A stopped Docker container pins its image until the container itself is removed. When stopped containers are holding images you don’t need anymore, run docker container prune first.

How Do You Remove Images by Age or Label?

Add –filter to docker image prune. until=240h removes images created more than 10 days ago, label=key targets images carrying a label, and label!=key targets images without it. Filters belong to the prune commands, and docker rmi accepts none.

FilterSyntaxRemoves
untiluntil=240h or until=2017-01-04T00:00:00Images created before that point
labellabel=deprecated or label=maintainer=johnImages with that label or value
label!=label!=maintainerImages without that label

docker image prune -a –force –filter “until=240h” ran in Docker’s documentation example against five local images and reported 792.6 MB reclaimed (Docker Docs, 2026).

Filters combine in a predictable way. Use different keys and you get AND logic, so label=foo with until=24h removes images that carry label foo and are older than 24 hours. Repeat the same key and you get OR logic, so label=foo with label=bar catches images with either label.

Time values can be Go durations such as 10m or 1h30m, counted from the daemon machine’s clock. Date strings and Unix timestamps work as well.

The label!= form has no preview. docker image ls doesn’t support negative filtering, and the prune prompt still warns about all dangling images.

The usual home for this is a scheduled prune on a continuous integration runner, something like a nightly until=168h run.

How Do You Remove All Docker Images?

Run docker rmi -f $(docker images -q) on Linux and macOS, or pipe docker image ls -q through xargs docker rmi -f. Either one deletes every local image, so the next run or build has to re-pull or rebuild all of them.

On Linux and macOS the command substitution version is docker rmi -f $(docker images -q), and the xargs version is docker image ls -q | xargs docker rmi -f. PowerShell on Windows uses docker rmi -f (docker images -q).

The -f matters here. With an image ID, -f untags and removes every entry that matches that ID, which covers images carrying several tags (Docker Docs, 2026).

The $(…) part is Bash command substitution, and a Bash syntax cheat sheet explains the rest of it.

The upside is simple. One command clears every local tag, frees more disk than any other image command, and puts a CI runner or a cluttered laptop back into a known state.

The downsides are real, though. Every image re-pulls or rebuilds on next use, and images you never pushed to a registry are gone for good. Anything a container still references throws conflict errors. There’s no preview and no undo.

I’d reach for docker image prune -a first. It skips every image a container uses and still clears the rest, so save the remove-everything approach for a host you’re resetting anyway.

Which Docker Cleanup Command Should You Use?

Pick docker rmi for one named image, docker image prune for dangling leftovers, docker image prune -a for every unused image, and docker builder prune for build cache alone. docker system prune has the widest scope and also deletes stopped containers and unused networks.

CommandDeletesKeepsBest for
docker rmiThe named image or tagEverything elseOne known target
docker image pruneDangling imagesTagged imagesRebuild leftovers
docker image prune -aAll unused imagesImages containers useDisk pressure on a build host
docker system pruneStopped containers, unused networks, dangling images, unused build cacheTagged images, volumesBroad cleanup of a dev machine
docker builder pruneBuild cacheImages, containers, networksCache-only reclaim

docker rmi is the one command in that table that never prompts. The four prune variants ask for confirmation unless you add -f.

docker system prune -a is the wrong routine default when only images need cleaning.

Docker’s confirmation text lists stopped containers, unused networks and unused build cache before it deletes anything (Docker Docs, 2026). If images are all you care about, docker image prune -a leaves those other objects alone.

Volumes survive docker system prune unless you add –volumes, which removes anonymous volumes.

Each command has its own trade. docker rmi hits an exact target with no collateral damage, but a large cleanup needs a script around it. Plain docker image prune is a safe default for rebuild leftovers and skips every tagged image, though you won’t gain much on a host full of tagged images.

docker image prune -a clears every unused image in one go, and the next run pays the pull or rebuild cost. docker system prune reclaims images, containers, networks and cache with one command. The catch is that stopped containers you planned to restart are gone, and the prompt is your only checkpoint.

docker builder prune frees cache without touching images or containers. Your next build will recompute every cached step, so expect it to run slower once.

Why Does Docker Refuse to Remove an Image?

Docker refuses removal when the daemon finds a conflict: a running container, dependent child images, a stopped container, or extra tags. The Moby daemon source defines 4 conflict types, 2 hard and 2 soft, and only soft conflicts yield to -f.

ConflictClassError ends withResolution
Running containerHardimage is being used by running containerStop and remove the container
Dependent child imageHardimage has dependent child imagesRemove the child image first
Stopped containerSoftimage is being used by stopped containerRemove the container, or add -f
Multiple tagsSoftimage is referenced in multiple repositoriesUntag each, or use -f with the ID

Image-ID conflict messages follow one format: conflict: unable to delete IMAGE\_ID (cannot be forced) – reason. The parenthetical reads must be forced for soft conflicts (Moby daemon source).

Container conflicts

A container pins its image whether it runs or not.

  1. Copy the container ID at the end of the error message.
  2. Run docker stop on it if it is running.
  3. Run docker rm on it.
  4. Repeat the docker rmi command.

Removal by name:tag has its own guard. When one tag exists and a container was built from it, Docker returns a “must force” error because removal would leave a dangling image (Moby daemon source).

Child image and multi-repository errors

A dependent child image means another local image was built on this one, so the child has to go first. The multiple repositories error means several tags share one image ID, and rmi by ID then needs -f.

docker image ls -a shows intermediate images, which helps when you’re hunting for the child.

What force removal does

-f overrides soft conflicts, meaning stopped-container references and extra tag references. It does nothing for hard conflicts, which are running containers and dependent child images.

The docker image rm page says an image used by a running container cannot be removed unless you use -f. The Moby daemon source treats a running container as a hard conflict that -f does not override (Docker Docs, 2026; Moby).

In practice the daemon decides, and its own error text says “cannot be forced”. Neither source explains why they differ.

How Do You Clear Build Cache and Confirm the Space Was Reclaimed?

docker builder prune removes build cache separately from images, and adding -a widens it from dangling cache to all unused cache. Compare the command’s reported total and the host’s free space to confirm the result.

docker rmi and docker image prune leave build cache alone. docker system prune includes it, so use docker builder prune when the cache is your only target.

A few figures from Docker’s documentation (2026). docker builder prune has 4 options: -a, –filter, -f and –keep-storage. Docker’s example for age-based pruning is until=24h. docker system prune always removes unused build cache, including data from RUN –mount=type=cache, and –keep-storage sets how much disk space to keep for cache.

  1. Run docker system df and note the baseline.
  2. Run docker builder prune, or docker builder prune -a for all unused cache.
  3. Note the total the command reports.
  4. Run docker system df again and check free space on the host with df -h.

A build pipeline that rebuilds on every commit keeps refilling the cache. Schedule docker builder prune with –filter until=24h instead of running a one-off clean.

When Does Removing Docker Images Not Free Disk Space?

Removing docker images frees nothing when the space sits elsewhere: volumes, container logs, writable container layers, build cache, or a Docker Desktop disk image that keeps its size. Image removal shrinks the image store and nothing else.

Where the space sitsWhy image removal misses itWhat reclaims it
Volumes and bind mountsData lives outside image layersdocker volume prune, or –volumes on system prune
Container logsWritten by the logging driverLog rotation
Writable container layersOwned by containers, not imagesdocker container prune
Build cacheStored apart from imagesdocker builder prune

Docker’s storage documentation names log files, volumes and bind mounts, configuration files, memory written to disk and checkpoints as space that image sizes do not count. It adds that logs grow large when rotation is not configured (Docker Docs, 2026).

Named volume data has its own storage area, covered in where Docker volumes are stored.

Measure before you delete. docker system df -v prints separate usage tables for images, containers and local volumes. In Docker Desktop, the Images view shows how much disk space the selected images would reclaim before you commit to deleting them.

On Docker Desktop, images live in a Linux virtual machine with a configurable disk usage limit and disk image location (Docker Docs, 2026).

Docker’s documentation does not promise that the host file shrinks after a deletion. Check the file size on the host after pruning before you reset anything.

And if a CI job or orchestrator pulls the same images again, it will refill the space you just freed.

How Do You Remove Images in Docker Desktop, Docker Compose, Podman, and Kubernetes Nodes?

Docker Desktop deletes images from its Images view, docker compose down –rmi removes images a Compose project used, podman rmi mirrors the Docker command, and crictl rmi removes images on CRI nodes where the kubelet also garbage collects unused ones.

EnvironmentCommand or controlRemovesDifference from docker rmi
Docker DesktopBin icon or bulk DeleteSelected imagesRemove the container first for images in use
Docker Composedocker compose down –rmi local or allImages the services uselocal skips custom-tagged images
Podmanpodman rmi -fImage and its containers-f removes containers too
CRI nodecrictl rmiImage and all its tagsRemoves every tag, not one

Docker Desktop’s Images view sorts by In use, Unused and Dangling, and Docker’s documentation says an image used by a running or stopped container needs its container removed first (Docker Docs, 2026).

Through Docker Compose, docker compose down removes service containers and networks by default, so images stay unless you pass –rmi. With –rmi local only images without a custom tag go. With –rmi all every image the services use is removed.

Podman’s rmi and image rm are the same command too, and podman rmi -a -f removes every image plus the containers using them (Podman docs). Docker’s -f never removes containers.

podman rmi also deletes dangling parent images along with the target unless you add –no-prune, and it returns a distinct exit status when child images or a container block the removal.

On Kubernetes nodes, the kubelet garbage collects unused images every 5 minutes and unused containers every minute (Kubernetes Docs, 2025). Once disk usage passes HighThresholdPercent, it deletes the least recently used images first until usage falls to LowThresholdPercent.

imageMaximumGCAge removes images unused longer than a set duration such as 12h45m, and the timer resets when the kubelet restarts. crictl images -q lists image IDs on the node, and crictl rmi removes an image by ID or reference along with all of its tags.

Kubernetes advises against external garbage collection tools on nodes because they can break kubelet behavior. Nodes usually run containerd or another CRI runtime, and this comparison of how Kubernetes and Docker differ explains why the Docker CLI is often missing.

FAQ on How To Remove Docker Images

What does “no such image” mean when running docker rmi?

The daemon found no local image matching your reference. Typos cause it, and so does leaving off the tag (Docker defaults to latest), or the image may already be gone. Copy the exact name:tag or ID from docker image ls -a.

Does removing a Docker image delete its containers?

No. Docker never removes containers during image removal. With -f, docker rmi deletes the image despite a stopped-container reference and leaves the container in place. Podman differs here, since podman rmi -f removes the containers too.

Is docker system prune safe on a production host?

It deletes stopped containers, unused networks, dangling images and unused build cache after a single prompt. Volumes survive unless you add –volumes. Production hosts fit docker image prune -a with an until filter better, and Kubernetes nodes should be left to the kubelet.

How do you delete an image from Docker Hub or a private registry?

docker rmi removes only the local copy. Registry deletion needs registry-side tooling such as skopeo delete, and some registries block remote deletion through a CLI. Check your registry’s own interface first.

Do image removal commands differ between Ubuntu and Windows?

The Docker CLI syntax is identical. Only the shell differs. Linux uses $(docker images -q) and PowerShell uses (docker images -q). Windows containers use the windowsfilter storage driver, and Docker Desktop adds its virtual disk on top.

What Should You Fix First in How To Remove Docker Images?

Work in order of rising blast radius. Dangling images go first, age-filtered unused images second, and a wider docker system prune only on hosts that rebuild everything from source. That order frees space at the lowest cost per pass.

It’s slower than one big command. Each pass can be checked with docker system df before the next one starts, and that’s the point.

This position was verified on 29 September 2026 against Docker Docs and the Moby daemon source. If the -f wording on the docker image rm page changes, or the daemon’s conflict classes do, the force advice changes with it.

Once the disk space is back, rebuild the image set and carry on by creating a Docker container from it.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.