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
- You run
docker rmi IMAGEordocker image rm IMAGE. The CLI resolves the argument as a local tag, digest, image ID, or unique image ID prefix. - 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.
- 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.
- If the image has several tags, Docker may remove only the tag you named. Other tags can keep the same image ID alive.
- If no tags, containers, child images, or cache records need the image object, Docker can delete the image object and unreferenced layers.
- Docker reports each removed name as
Untaggedand each deleted content object asDeleted. The visible reclaimed disk space may be smaller than the listed image size because layers are shared. - 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 rmin new documentation, but recognizedocker rmias 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 lsbefore cleanup so you can see tags, image IDs, and possible duplicate references. - Run
docker container ls --allwhen image removal fails; stopped containers still block image deletion. - Use
docker rmfor containers anddocker rmiordocker image rmfor images. - Do not expect the full displayed image size to be reclaimed. Docker layers are shared across images.
- Use
docker image prunefor dangling images after repeated builds, and read the confirmation prompt before accepting. - Use
docker image prune -aonly when you understand that it removes unused images, not just dangling ones. - Avoid using
--forceas 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
- Pull
alpine:3.20, list it, remove it by tag, then list it again. Expected end state: the final listing no longer showsalpine:3.20. - 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. - 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 pruneis appropriate.
Summary
docker rmianddocker image rmremove 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.
Untaggedmeans Docker removed a name.Deletedmeans Docker removed an image object or layer.docker rmremoves containers;docker rmiremoves images.--forceis 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.
