docker rmi and Removing Images

docker rmi removes Docker images from your local machine. It matters because pulled and built images can consume a lot of disk space, but deleting the wrong image can interrupt a workflow or fail because a container still depends on it.

The modern command is docker image rm, while docker rmi is the older shorthand that remains widely used. Both remove image references and, when possible, the underlying image layers from the local Docker image store.

Overview: How Image Removal Works

A Docker image is a read-only template made from stacked filesystem layers and an image configuration object. A container is different: it is a created runtime instance with its own thin writable layer on top of those read-only image layers. This distinction is the main reason image removal sometimes surprises people. Removing a stopped container with docker rm does not remove the image it was created from, and removing an image with docker rmi is blocked when an existing container still references that image.

Images are usually named by repository and tag, such as nginx:1.27-alpine, redis:7.2-alpine, or my-api:1.0. A tag is a local name that points to image content. Multiple tags can point to the same image ID. When you remove one tag, Docker may only delete that name. The actual image object and shared layers remain if another tag, another image, a build cache record, or a container still needs them.

Layers are content-addressed and shared. If my-web:1.0 was built from nginx:1.27-alpine, both may share base layers. Deleting my-web:1.0 does not necessarily free the full size shown by docker image ls, because some layers may still be used by nginx:1.27-alpine or another descendant image. Docker prints Untagged when it removes a name and Deleted when it removes an unreferenced layer or image object.

docker rmi works only on the local Docker daemon. It does not delete an image from Docker Hub, GitHub Container Registry, ECR, or any other remote registry. If you pushed my-api:1.0 and then run docker rmi my-api:1.0, the local copy is removed, but the registry copy remains until you delete it through that registry’s own tools or API.

On Docker Desktop for macOS and Windows, Linux image data lives inside Docker Desktop’s managed Linux VM. On native Linux, it lives under Docker’s configured storage area. The command is the same in both cases: the Docker CLI asks the daemon to remove local image references, and the daemon decides which objects and layers are safe to delete.

Syntax

The old and new forms are equivalent for normal use:

docker rmi [OPTIONS] IMAGE [IMAGE...]
docker image rm [OPTIONS] IMAGE [IMAGE...]
Part or option Meaning
IMAGE An image reference, image ID, or digest, such as nginx:1.27-alpine, my-api:1.0, or a unique image ID prefix.
-f or --force Force removal of the image reference. This can remove multiple tags for the same image ID, but it still will not delete layers needed by running containers.
--no-prune Do not delete untagged parent images that would otherwise be pruned as part of the removal.
IMAGE... You can provide more than one image in the same command to remove several references together.

docker rmi is best when you know exactly which local image reference you want to remove. For broad cleanup, Docker also provides docker image prune for dangling or unused images and docker system prune for a wider cleanup across containers, networks, build cache, and images. Those prune commands are powerful and should be used deliberately.

Examples

Example 1: Remove One Pulled Image by Tag

docker pull alpine:3.20
docker image ls alpine:3.20
docker rmi alpine:3.20

Output:

3.20: Pulling from library/alpine
Status: Downloaded newer image for alpine:3.20
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
alpine       3.20      1e42bbe25081   4 weeks ago   7.8MB
Untagged: alpine:3.20
Deleted: sha256:1e42bbe25081example

The pull stores the image locally, the listing confirms the tag, and docker rmi removes that local reference. If no other tag, container, or image uses the same content, Docker can also remove the image object and some layers. Your image ID and exact output will differ.

Example 2: A Container Blocks Image Removal

docker run --name temp-nginx -d nginx:1.27-alpine
docker rmi nginx:1.27-alpine

Output:

f3a5b2c1d0e9example
Error response from daemon: conflict: unable to remove repository reference "nginx:1.27-alpine" - container f3a5b2c1d0e9 is using its referenced image

Docker refuses to remove the image because the container temp-nginx was created from it. The container can be running or stopped; either way, its metadata still references the image. Remove the container first, then remove the image:

docker rm -f temp-nginx
docker rmi nginx:1.27-alpine

Output:

temp-nginx
Untagged: nginx:1.27-alpine
Deleted: sha256:4c84c57db0b7example

docker rm -f stops and removes the container. Only after that can Docker remove the local image reference. This is why cleanup often starts with docker container ls --all: containers are the most common reason docker rmi fails.

Example 3: Remove Multiple Local Images

docker pull redis:7.2-alpine
docker pull busybox:1.36
docker image rm redis:7.2-alpine busybox:1.36

Output:

Untagged: redis:7.2-alpine
Deleted: sha256:9f5c3d2a1b0eexample
Untagged: busybox:1.36
Deleted: sha256:65ad0d468eb1example

The command accepts more than one image reference. This is useful for focused cleanup after a test or workshop. It is safer than broad pruning because each target is visible in the command.

Example 4: Remove Dangling Images After Rebuilds

docker image ls --filter "dangling=true"
docker image prune

Output:

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
<none>       <none>    a1b2c3d4e5f6   10 minutes ago   142MB
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:a1b2c3d4e5f6example
Total reclaimed space: 142MB

Dangling images are untagged image objects, often left behind when you rebuild the same tag and the old image loses its name. docker image prune removes dangling images by default. It is not the same as docker rmi, but it is closely related cleanup tooling and often solves the disk-space problem that leads people to image removal.

How It Works Step by Step

  1. You run docker rmi IMAGE or docker image rm IMAGE. The CLI resolves the argument as a local tag, digest, image ID, or unique image ID prefix.
  2. The CLI sends the request to the Docker daemon through the active Docker context. The operation happens in the daemon’s local image store, not in a remote registry.
  3. The daemon checks whether containers reference the image. If a container exists, Docker normally rejects removal because that container needs the image metadata and read-only layers.
  4. If the image has several tags, Docker may remove only the tag you named. Other tags can keep the same image ID alive.
  5. If no tags, containers, child images, or cache records need the image object, Docker can delete the image object and unreferenced layers.
  6. Docker reports each removed name as Untagged and each deleted content object as Deleted. The visible reclaimed disk space may be smaller than the listed image size because layers are shared.
  7. If you use --force, Docker is more aggressive about removing image references, but shared layers and running container dependencies still protect required content.

The safest mental model is reference counting. Docker removes a name first, then removes content only when nothing else needs that content. This is why a command can succeed and still not free much disk space, and why two image rows with the same image ID should be treated as two names for one underlying object.

Common Mistakes

Confusing docker rm and docker rmi

docker rm nginx:1.27-alpine

This is wrong because docker rm removes containers, not images. It expects a container name or container ID. Use docker rmi or the clearer modern form:

docker image rm nginx:1.27-alpine

Trying to Remove an Image Before Removing Its Containers

docker run --name old-api -d nginx:1.27-alpine
docker stop old-api
docker rmi nginx:1.27-alpine

Stopping the container is not enough. A stopped container still references its image. Remove the container, then remove the image:

docker rm old-api
docker rmi nginx:1.27-alpine

Assuming –force Is Normal Cleanup

docker rmi -f my-api:1.0

--force can be useful when you intentionally want to remove a tag or image ID despite conflicts such as multiple tags. It should not be your default habit. First inspect what exists with docker image ls and docker container ls --all, because forceful cleanup can remove names that teammates or scripts expect locally.

Believing Local Removal Deletes the Registry Copy

docker rmi ghcr.io/example/my-api:1.0

This only removes the local reference. The image in the registry still exists. To delete remote content, use the registry provider’s UI, CLI, retention policy, or API. Docker’s local image removal command does not reach back into the registry and delete published artifacts.

Deleting the latest Tag Without Understanding Tags

docker rmi redis:latest

This removes your local redis:latest reference, but it does not say anything about the newest Redis release and it does not remove other local tags such as redis:7.2-alpine. In production, avoid relying on latest at all. Specific tags or tested digests make cleanup and deployment much easier to reason about.

Best Practices

  • Prefer docker image rm in new documentation, but recognize docker rmi as the common shorthand.
  • Remove by explicit repository and tag, such as my-api:1.0, when humans need to understand the command later.
  • Run docker image ls before cleanup so you can see tags, image IDs, and possible duplicate references.
  • Run docker container ls --all when image removal fails; stopped containers still block image deletion.
  • Use docker rm for containers and docker rmi or docker image rm for images.
  • Do not expect the full displayed image size to be reclaimed. Docker layers are shared across images.
  • Use docker image prune for dangling images after repeated builds, and read the confirmation prompt before accepting.
  • Use docker image prune -a only when you understand that it removes unused images, not just dangling ones.
  • Avoid using --force as routine cleanup. Inspect the conflict and remove containers or specific tags intentionally.
  • Remember that local image removal does not delete registry images or undo a previous docker push.

Practice Exercises

  1. Pull alpine:3.20, list it, remove it by tag, then list it again. Expected end state: the final listing no longer shows alpine:3.20.
  2. Create a container from nginx:1.27-alpine, stop it, and try to remove the image. Hint: the stopped container still references the image, so identify and remove the container before trying again.
  3. Build the same local image tag twice in a small test project, then list dangling images. Expected end state: you can explain why old untagged image objects appear and when docker image prune is appropriate.

Summary

  • docker rmi and docker image rm remove local image references and, when possible, unreferenced image content.
  • Images are read-only layered templates; containers are instances with a writable layer and can block image deletion.
  • Removing a tag is not always the same as deleting all underlying layers because tags, containers, child images, and shared layers may still reference them.
  • Untagged means Docker removed a name. Deleted means Docker removed an image object or layer.
  • docker rm removes containers; docker rmi removes images.
  • --force is for intentional conflict handling, not a replacement for understanding what references the image.
  • Use explicit tags, inspect containers first, and use prune commands carefully for broader cleanup.