List & Inspect Images
Learn how to view, filter, and inspect Docker images on your local system to understand their contents and metadata.
List & Inspect Images
You've pulled a few images. Maybe you've built one too. Now the natural question is "what's actually sitting on my machine, and how do I understand what's inside these images?"
Docker gives you a handful of commands to answer exactly that. This guide walks through all of them in plain English.
How to See All Your Local Images
The most basic command is docker images. Run it and you'll get a table of every image stored on your machine:
# List all images
docker images
# Identical alternative
docker image ls
# Include intermediate build layers
docker images -a
# Show only image IDs
docker images -q
# Filter by repository name
docker images nginx
# Filter by reference (name + tag)
docker images "nginx:1.25"
Sample output:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 141MB
postgres 16 6e52a4f81b47 3 weeks ago 432MB
alpine 3.18 c1aabb73d233 3 weeks ago 7.33MB
node 18-alpine 8cdf5e4fca3f 4 weeks ago 127MB
Here's what each column actually means:
| Column | What it tells you |
|---|---|
REPOSITORY | The image name (registry is omitted if it's from Docker Hub) |
TAG | The version or variant (e.g. latest, 16, 3.18-alpine) |
IMAGE ID | A short fingerprint of the image (first 12 characters of its full hash) |
CREATED | When the image was built |
SIZE | How much disk space it takes up on your machine, uncompressed |
One thing worth knowing about the SIZE column: if two images share layers (for example, both use the same Ubuntu base), that shared layer is only stored once on disk, but it still gets counted in each image's size. So the total disk usage is usually less than the sum of all the sizes you see listed.
Filtering and Formatting the Image List
As you pull more images, the list gets long. These commands help you to filter the images:
# Show dangling images (untagged leftovers from old builds)
docker images --filter dangling=true
# Show images created before a specific image
docker images --filter before=nginx:latest
# Show images created after a specific image
docker images --filter since=alpine:3.18
# Custom output (show only name, tag, and size)
docker images --format "{{.Repository}}:{{.Tag}} - {{.Size}}"
Dangling images are the most common thing to clean up. They're leftover layers from previous builds that no longer have a name or tag attached to them.
How to Inspect What's Inside an Image
docker images tells you what you have. docker inspect tells you everything about a specific image. It returns a detailed JSON document packed with metadata:
# See the full details of an image
docker inspect nginx:latest
# Extract just the default command the image runs
docker inspect --format='{{.Config.Cmd}}' nginx
# See all environment variables baked into the image
docker inspect --format='{{.Config.Env}}' nginx
# See which ports the image expects to be open
docker inspect --format='{{.Config.ExposedPorts}}' nginx
# List all the layers that make up the image
docker inspect --format='{{.RootFS.Layers}}' nginx
The --format flag uses Go templates to pull out just the field you care about, so you don't have to wade through the entire JSON output. Here's a taste of what the full output contains:
{
"Id": "sha256:605c77e624dd...",
"RepoTags": ["nginx:latest"],
"Created": "2022-01-01T00:00:00Z",
"Config": {
"Env": ["PATH=/usr/local/sbin:...", "NGINX_VERSION=1.23.3"],
"Cmd": ["nginx", "-g", "daemon off;"],
"ExposedPorts": { "80/tcp": {} },
"WorkingDir": ""
},
"RootFS": {
"Layers": [
"sha256:ad6562704f37...",
"sha256:3a6d0e8b2b4c...",
"sha256:c8f1b15a9c1f..."
]
}
}
The most practically useful fields for beginners are ExposedPorts (which port your container will listen on), Env (what environment variables are pre-configured), and Cmd (what command runs when you start the container).
Hands-On Practice: List and Inspect an Image
# Step 1: See all images currently on your machine
docker images
# Step 2: Inspect the nginx image to find which port it exposes
docker inspect --format='{{.Config.ExposedPorts}}' nginx
# Step 3: Check the default command nginx runs on startup
docker inspect --format='{{.Config.Cmd}}' nginx
After step 2, you should see map[80/tcp:{}] which tells you nginx listens on port 80. That's the port you'll need to map when you run the container.
How to See an Image's Layer History
Every Docker image is built up from layers, one on top of the other, like a stack of transparent sheets. docker history shows you every layer, what command created it, and how much space it takes:
docker history nginx:latest
IMAGE CREATED CREATED BY SIZE
605c77e624dd 2 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemo… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B
<missing> 2 weeks ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 2 weeks ago /bin/sh -c apt-get install -y nginx 58.4MB
<missing> 2 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.23.3 0B
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:abc123... in / 80.4MB
A few things to notice here:
Layers showing 0B are metadata-only, things like setting an environment variable (ENV) or declaring a port (EXPOSE). They don't add any actual files to the image, so they take up no space.
The big layers (58.4MB, 80.4MB) are where real files were added, like installing nginx, or laying down the base OS filesystem.
<missing> in the IMAGE ID column is completely normal. It just means the intermediate layer isn't stored as a standalone image on your machine, only the final result is kept.
How to Check How Much Disk Space Docker Is Using
Docker can quietly eat up a lot of disk space over time because of old images, stopped containers, unused volumes, and build cache all accumulate. This command gives you a clear overview:
# Quick summary
docker system df
# Full breakdown with details
docker system df -v
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 8 3 2.1GB 1.4GB (66%)
Containers 2 1 45MB 0B (0%)
Local Volumes 3 2 512MB 156MB (30%)
Build Cache 12 0 890MB 890MB (100%)
The RECLAIMABLE column is the key one. It shows how much space you could free up by cleaning things out. In this example, 890MB of build cache can be fully reclaimed since none of it is actively in use.
Key Takeaways
docker imagesis your starting point. It lists everything stored locally with the name, tag, ID, and size.- The SIZE column can be misleading: shared layers are counted per image but only stored once on disk, so actual usage is lower.
docker inspectgives you deep metadata about an image, especially useful for finding exposed ports, environment variables, and startup commands.- Use
--formatwithdocker inspectto extract just the field you need instead of reading through pages of JSON. docker historyshows you every layer in an image and what created it. It is important to understand what's actually inside a third-party image.docker system dfshows how much disk space Docker is using across images, containers, volumes, and build cache and how much is safe to clean up.
Frequently Asked Questions
What's the difference between docker images and docker image ls?
They do exactly the same thing. docker image ls is the newer, more structured syntax that Docker introduced as part of a broader command reorganization.
Why does CREATED show a date from weeks ago even though I just pulled the image?
The CREATED date is when the image was built by whoever published it, not when you downloaded it. If you pulled nginx today but the image was built two weeks ago, you'll see two weeks ago.
What are dangling images and should I delete them?
Dangling images are untagged layers left behind from previous builds. For example, when you rebuild an image and the old version loses its tag. They're generally safe to delete with docker image prune.
Why do I see <missing> in docker history output?
It means the intermediate layer isn't stored as a separate image on your machine, only the final image is kept locally. This is normal and doesn't indicate anything is broken.
The sizes in docker images add up to way more than my actual disk usage. Why?
Because shared layers are counted in each image's size but only stored once on disk. Two images that both use the same Alpine base will each show the Alpine layer in their size, but your disk only holds one copy of it. docker system df gives a more accurate picture of real disk usage.