List, Filter and Inspect Local Docker Images
You will finish with a reliable way to find images in the local Docker image store, distinguish tags from image IDs, and turn the result into concise output for a shell script. The examples use Docker CLI 29.8.1 from docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble, so check your own version if the output or experimental options differ.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need the Docker CLI and access to a running Docker daemon. Listing images is normally a read-only operation and does not need elevated privileges. If your account is not allowed to access the daemon socket, fix that access through your normal Docker installation process or use the approved administrative route. Do not casually add users to the docker group: access to the daemon is effectively high privilege.
1. Check the installed command
Start with the command and package version. This confirms which syntax the examples should match:
$ docker --version
Docker version 29.8.1, build ...
$ dpkg-query -W -f='${Package} ${Version}\n' docker-ce-cli
docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble
The exact build suffix can vary. The manpage describes docker images as an alias for docker image ls, and the command also accepts docker image list. Pick one spelling and use it consistently in scripts. The grouped docker image ls form makes it clearer that this is image inventory, not container status.
Checkpoint: ask the binary for its supported options before copying an example from another Docker installation:
$ docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
2. List the images currently available
Run the default listing:
$ docker image ls
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
alpine:3 294b683cb724 13MB 3.94MB
alpine:latest 294b683cb724 13MB 3.94MB
hello-world:latest 5e2309035332 25.9kB 9.49kB
Your table will contain different repositories, tags, ages and sizes. The default view hides intermediate and dangling images. A repeated ID is not necessarily a duplicate: several tags can refer to the same underlying image, as alpine:3 and alpine:latest do above. The displayed size is the image's cumulative local size, so do not add repeated rows together when estimating storage.
To restrict the list to one repository or tag, pass the reference after the options:
$ docker image ls alpine:3
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine 3 294b683cb724 ... 13MB
If nothing matches, Docker prints an empty table. That means the image is not present under that local reference; it does not pull the image and it does not prove that a similarly named remote image is unavailable.
3. Make missing images and duplicate tags visible
Use --all when you need intermediate layers and dangling images:
$ docker image ls --all
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 1a2b3c4d5e6f ... 13MB
alpine latest 294b683cb724 ... 13MB
Rows containing <none> are a description of an untagged local object, not shell syntax. Do not remove them merely because they look untidy. They may still be useful for build caches, and removal belongs to a separate cleanup decision.
For scripts or support tickets that need an unambiguous identifier, use --no-trunc:
$ docker image ls --no-trunc alpine:3
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine 3 sha256:294b683cb724... ... 13MB
The long ID is more suitable for records than the shortened display ID. Exact creation times and the full value vary by image, so treat the row above as a shape, not a fixed result.
4. Filter the inventory
Filters use key=value. The installed command supports filters such as dangling, label, before, since and reference. For example, match only local Alpine references:
$ docker image ls --filter 'reference=alpine:*'
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine 3 294b683cb724 ... 13MB
alpine latest 294b683cb724 ... 13MB
Quote the filter so the shell does not expand the wildcard before Docker receives it. To find dangling images without changing anything, use:
$ docker image ls --filter 'dangling=true'
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 1a2b3c4d5e6f ... 13MB
An empty result is a useful result. Do not turn an inventory command into a deletion pipeline such as docker rmi $(docker image ls ...) until you have reviewed every ID and checked whether containers depend on it.
5. Show digests when provenance matters
Tags are convenient names and can move. Add --digests when you need the content-addressed digest recorded alongside the tag:
$ docker image ls --digests alpine
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
alpine latest <none> 294b683cb724 ... 13MB
A locally built image may have no registry digest, shown as <none>. That is not an error and it is not the same thing as the image ID. When a registry digest is present, record the full sha256:... value if you need to reproduce a deployment. The listing command does not fetch a missing digest.
6. Produce stable, smaller output
Use --quiet when a later command needs only image IDs:
$ docker image ls --quiet alpine
294b683cb724
This is still output from a command intended for humans, so avoid assuming a particular ordering. For a report, choose the fields explicitly with a Go template:
$ docker image ls --format 'table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}'
REPOSITORY TAG ID SIZE
alpine 3 294b683cb724 13MB
alpine latest 294b683cb724 13MB
Useful fields include .ID, .Repository, .Tag, .Digest, .CreatedAt and .Size. The table prefix adds column headings. Use --format json when one JSON object per image is easier for your consumer than parsing aligned columns:
$ docker image ls --format json | head -1
{"Containers":"N/A","CreatedAt":"...","Digest":"<none>","ID":"294b683cb724","Repository":"alpine","Size":"13MB","Tag":"latest"}
Keep the single quotes around templates in a POSIX shell. They protect the braces and dollar-like template syntax from accidental shell interpretation.
7. Handle the common failures safely
If Docker reports that it cannot connect to the daemon, the listing itself has not changed anything. Check the active context and daemon status using your site's normal runbook before restarting services. A service restart can disrupt running containers and is not required just to learn the command's flags.
If the command succeeds but an expected repository is absent, check the exact spelling, tag and active Docker context. A different context has a different image store. Do not pull an image as a diagnostic unless you have confirmed the registry, tag, platform and storage impact.
docker image ls is read-only. This guide therefore has no undo command. If you later decide to prune images, treat that as a separate, destructive operation: review the candidates, confirm no required container or rollback depends on them, and retain a recoverable source such as the original registry or an exported archive.
Done means
- You checked the installed Docker CLI and package version.
- You can list all ordinary local image tags and understand repeated IDs.
- You know when
--all,--no-truncand--digestschange the evidence shown. - You can filter by a quoted reference or dangling status without deleting anything.
- You can produce IDs, a table or JSON-shaped records for the next tool.
- You have kept image listing separate from pulling, removing and service-disrupting maintenance.