Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

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

Sponsored

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 images shows dozens of entries you don’t recognize.
  • docker build suddenly 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:

  1. Remove by tag – only if no container is using it. bash docker rmi myapp:latest
  2. Force remove – use -f only when you know the container is garbage. bash docker rmi -f <image-id>
  3. Remove all dangling images – the single safest cleanup command. bash docker image prune
  4. Remove everything unused – add -a to prune all images without at least one associated container. bash docker image prune -a

Blockquote callout – Always run docker ps -a before 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 -f on an image used by a running container will force-delete it, causing the container to crash or behave erratically. Always check docker ps -a --filter ancestor=<image> first.
  • Assuming docker image prune -a is safe for daily use. It removes every image without an active container, including cached base images that speed up future builds. Use docker 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 use docker rmi <image-id> directly.
  • Ignoring dangling <none>:<none> images. These consume disk space and slow down docker images output. Run docker image prune weekly to reclaim space and keep your image list clean.

Variations

  1. Use docker image ls instead of docker images — both work identically, but the longer form is more explicit in scripts.
  2. For programmatic inspection, parse JSON with docker inspect --format '{{json .}}' <image> | jq to filter specific fields like .ContainerConfig.Env.
  3. 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 prune weekly on their laptop to reclaim gigabytes of space from abandoned Python image layers.
  • A CI pipeline uses docker inspect --format '{{.Id}}' $IMAGE to tag built images with their SHA256 digest for immutable releases.
  • A production on-call engineer uses docker images --filter "dangling=true" -q | xargs docker rmi to free disk space on a VM running out of inodes.

Key takeaways

  • docker images lists all local images; docker image prune removes only dangling (untagged) images safely.
  • docker inspect and docker history reveal metadata and layer commands — essential for debugging oversized images.
  • docker rmi removes an image by tag or ID; use -f only after verifying no container depends on it.
  • Dangling images (<none>:<none>) are always safe to remove and should be cleaned regularly.
  • docker image prune -a is aggressive — it deletes all images without active containers, breaking build caches.
  • Always run docker ps -a before mass removal to avoid accidentally breaking containers.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.