Docker Image Management
Learn how to list, inspect, and remove Docker images in this practical tutorial for developers. Hands-on exercises and troubleshooting included.
Focus: list, inspect, and remove docker images
You’ve built a Docker image, maybe even launched a container — but your local disk is silently filling up with unused layers, old tags, and dangling none images. Without knowing how to list, inspect, and remove Docker images systematically, you’ll waste storage, slow down builds, and eventually hit scary no space left on device errors. This lesson gives you the exact commands to audit your image inventory, peek into an image’s internals, and clean up the mess — safely and repeatably.
The problem this lesson solves
Every docker build or docker pull adds an image to your local store. Over time, that store becomes a graveyard of deprecated tags, intermediate layers, and abandoned experiments. The immediate symptoms are familiar:
docker imagesshows dozens of entries you don’t recognize.docker buildsuddenly takes minutes because the cache is full of stale layers.- Hard disk warnings appear on your laptop or CI node.
The root cause is simple: containers are ephemeral, but images are persistent. Without explicit list, inspect, and remove Docker images commands, you’re accumulating digital debt. Worse, blindly deleting everything with docker rmi -f can break running containers or remove images that a colleague still needs.
Pro Tip – Disk space is cheap until it isn’t. On cloud VMs with 10 GB root volumes, an untrimmed image cache is the first thing that crashes production builds.
Core concept / mental model
Think of Docker images as layered file-system snapshots, similar to Git commits. Each FROM, RUN, or COPY instruction creates a new read-only layer. The image itself is just the label (repository + tag) that points to the top layer of that stack.
┌─────────────────────┐
│ myapp:latest │ ← tag (like a Git branch name)
├─────────────────────┤
│ layer: ADD . /app │ ← head layer
├─────────────────────┤
│ layer: RUN pip … │
├─────────────────────┤
│ layer: FROM python │ ← base image
└─────────────────────┘
Listing shows you all tags on your machine. Inspecting reveals the metadata (environment variables, exposed ports, history of layers). Removing dereferences the tag and garbage-collects unreferenced layers.
Key definitions:
- Image ID – a 64-char SHA256 digest that uniquely identifies the content.
- Tag – a human-readable alias (e.g.,
myapp:latest). - Dangling image – an image that has no tag and is not used by any container (
<none>:<none>). These are safe to remove. - Intermediate container – the temporary container created during
docker build. It is automatically removed unless you use--rm=false.
How it works step by step
Step 1 – List images
docker images (or docker image ls) prints a table with REPOSITORY, TAG, IMAGE ID, CREATED, and SIZE.
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"
The --format flag turns the raw output into a custom table — useful for scripts.
Step 2 – Inspect an image
docker inspect <image> returns a massive JSON blob with layers, environment, command, architecture, and more.
For a human-readable history of how the image was built:
docker history <image>
This shows every layer’s ID, creation command, and size — perfect for debugging oversized images.
Step 3 – Remove images
Safety-first order:
- Remove by tag – only if no container is using it.
bash docker rmi myapp:latest - Force remove – use
-fonly when you know the container is garbage.bash docker rmi -f <image-id> - Remove all dangling images – the single safest cleanup command.
bash docker image prune - Remove everything unused – add
-ato prune all images without at least one associated container.bash docker image prune -a
Blockquote callout – Always run
docker ps -abefore mass removal. A stopped container still holds a reference to its image, preventing deletion.
Hands-on walkthrough
Example 1 – List your local images
docker images
Expected output (yours will differ):
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2b7d6430f78d 2 weeks ago 187MB
python 3.10 a6d0b5e50d2f 3 weeks ago 1.02GB
myapp v1.0 bf3c8e9a1f45 5 hours ago 345MB
Example 2 – Inspect an image’s layers
docker inspect nginx:latest --format '{{.Created}}'
Expected output: 2024-01-15T10:30:00.123456789Z
For full details (hundreds of lines):
docker inspect nginx:latest | head -50
Example 3 – Remove a single image
docker rmi myapp:v1.0
If the image is in use by a container, you’ll see:
Error response from daemon: conflict: unable to remove repository reference "myapp:v1.0" (must force) - container a1b2c3d4 is using its referenced image bf3c8e9a1f45
Solution: either remove the container first (docker rm a1b2c3d4) or force-remove the image with -f.
Example 4 – Clean all dangling images
docker image prune
Expected output:
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:abc123…
deleted: sha256:def456…
Total reclaimed space: 234.5 MB
Compare options / when to choose what
| Command | When to use | Risk level |
|---|---|---|
docker images |
Quick inventory, daily checks | None |
docker inspect <img> |
Debug build or port/volume details | None |
docker history <img> |
Audit layer sizes, find cache bloat | None |
docker rmi <tag> |
Remove a specific known image | Medium – may be referenced |
docker rmi -f <id> |
Delete an image in use (only if container is disposable) | High – breaks running containers |
docker image prune |
Remove all dangling <none> images |
Low – safe for daily cleanup |
docker image prune -a |
Remove all images without active containers | High – may delete cached base images needed for future builds |
Guideline: Use prune weekly, rmi for targeted deletions, and inspect only when you need to debug metadata. Never run prune -a in a shared CI runner without first checking which images your CI pipeline caches.
Troubleshooting & edge cases
“Image is being used by running container”
Docker refuses to remove an image if a container (even a stopped one) references it. Check with:
docker ps -a --filter "ancestor=<image-id>"
Then either remove the container or force-remove the image (docker rmi -f).
Dangling images accumulate despite docker system prune
Ensure you run docker image prune without -a — the -a flag removes all unused images, while docker system prune only removes dangling images by default.
“docker rmi” shows no output
If the image has multiple tags, docker rmi removes the tag but not the image itself. Use docker rmi $(docker images -q) to delete all images (dangerous) or docker rmi <image-id> to remove the underlying layers.
Disk space not reclaimed after removal
Docker image deletion marks layers for garbage collection, but the actual disk space is freed only after you run docker system prune or restart the Docker daemon. On Linux, you may also need to clean /var/lib/docker/overlay2 manually — but this is rare.
Blockquote callout – If you see "operation not permitted" when removing an image on macOS or Windows, restart Docker Desktop. The daemon can lock image layers.
What you learned & what's next
You now know how to list, inspect, and remove Docker images confidently:
docker images– list all images with tags, IDs, and sizes.docker inspect– read JSON metadata for any image.docker history– view layer commands and size.docker rmi– remove by tag or ID.docker image prune– clean dangling images safely.docker image prune -a– aggressive clean of all unused images.
What’s next: In the next lesson, you’ll learn to manage Docker containers — starting, stopping, restarting, and cleaning them. You’ll combine docker ps, docker start, docker stop, and docker rm to control the container lifecycle. The image skills you just built are the prerequisite for keeping your container host lean and reliable.
Practice recap
Run docker images to see your current image list. Pick one image you no longer need (like a test image or old tutorial), inspect it with docker inspect, then remove it with docker rmi. Finally, run docker image prune to clear any dangling layers. Write down how much disk space you reclaimed.
Common mistakes
- Running
docker rmi -fon an image used by a running container will force-delete it, causing the container to crash or behave erratically. Always checkdocker ps -a --filter ancestor=<image>first. - Assuming
docker image prune -ais safe for daily use. It removes every image without an active container, including cached base images that speed up future builds. Usedocker image prune(without-a) instead for routine cleanup. - Forgetting that
docker rmi <tag>only removes the tag if the image has multiple tags. The underlying image ID remains until all tags are removed or you usedocker rmi <image-id>directly. - Ignoring dangling
<none>:<none>images. These consume disk space and slow downdocker imagesoutput. Rundocker image pruneweekly to reclaim space and keep your image list clean.
Variations
- Use
docker image lsinstead ofdocker images— both work identically, but the longer form is more explicit in scripts. - For programmatic inspection, parse JSON with
docker inspect --format '{{json .}}' <image> | jqto filter specific fields like.ContainerConfig.Env. - On CI servers, combine
docker system prune -af --filter "until=24h"to remove images older than 24 hours without deleting fresh caches.
Real-world use cases
- A developer runs
docker image pruneweekly on their laptop to reclaim gigabytes of space from abandoned Python image layers. - A CI pipeline uses
docker inspect --format '{{.Id}}' $IMAGEto tag built images with their SHA256 digest for immutable releases. - A production on-call engineer uses
docker images --filter "dangling=true" -q | xargs docker rmito free disk space on a VM running out of inodes.
Key takeaways
docker imageslists all local images;docker image pruneremoves only dangling (untagged) images safely.docker inspectanddocker historyreveal metadata and layer commands — essential for debugging oversized images.docker rmiremoves an image by tag or ID; use-fonly after verifying no container depends on it.- Dangling images (
<none>:<none>) are always safe to remove and should be cleaned regularly. docker image prune -ais aggressive — it deletes all images without active containers, breaking build caches.- Always run
docker ps -abefore mass removal to avoid accidentally breaking containers.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.