Read Image Layers with docker history

An image just misbehaved in production, and docker history is how you see exactly what commands built it. This guide gives you a repeatable way to inspect how an image was assembled, expose commands that the default table shortens, and select a particular platform when an image has more than one. The examples match Docker Community Edition CLI 29.8.1, installed here as package docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble.

Allow about ten minutes. You need the Docker CLI, access to a running Docker daemon, and an image available in the local image store. These commands only read image metadata. They do not remove layers, rebuild an image, or change a tag. Reading history may reveal commands, paths or other build details that you did not intend to disclose, so treat the output as potentially sensitive.

1. Check the installed command

Start with the local command and package version. This is an ordinary command and does not need elevated privileges:

$ docker --version
Docker version 29.8.1, build 4a63305
$ dpkg-query -W -f='${Package} ${Version}\n' docker-ce-cli
docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble

The standalone docker history command is an alias for docker image history. The synopsis is:

$ docker history [OPTIONS] IMAGE

Use an image reference that is present locally, such as IMAGE_NAME:TAG or a local image ID. Do not replace that placeholder with a tag you have not checked.

Checkpoint: List local images and choose one deliberately:

$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
IMAGE_NAME   TAG       IMAGE_ID       ...           ...

The repository, tag and ID above are placeholders. Your output will contain the images on your host. If Docker reports that it cannot connect to the daemon, fix that access problem first; do not add sudo automatically. On a host where Docker access is deliberately restricted, ask an administrator to grant the appropriate group or service access rather than changing permissions casually.

2. Read the normal layer table

Run the command with your chosen image reference:

$ docker history IMAGE_NAME:TAG
IMAGE        CREATED       CREATED BY                         SIZE      COMMENT
IMAGE_ID     ...           /bin/sh -c ...                     ...       ...

The table is ordered from the image's newest layer towards its base. The columns identify the layer, when it was created, the command associated with it, its reported size, and any comment. Exact IDs, dates and commands depend on the image.

The default output is designed for a terminal. Long values in the IMAGE and CREATED BY columns can be shortened, and the human-readable size and age formatting is enabled by default in this installed version. History is not a Dockerfile: imported images or squashed builds may have less useful command information, and a layer's command does not prove which files changed.

3. Show complete values when investigating a layer

Use --no-trunc when the shortened command or ID is the detail you need:

$ docker history --no-trunc IMAGE_NAME:TAG
IMAGE                                                             CREATED       CREATED BY                                      SIZE      COMMENT
sha256:FULL_IMAGE_ID                                             ...           /bin/sh -c ...                                  ...       ...

This option affects presentation only. It does not recover build steps that were never recorded. If an image contains secrets in a command or comment, showing the full value can put them into your terminal scrollback, a log collector or a ticket. Before redirecting output, decide whether those destinations are appropriate.

Checkpoint: Compare a quiet ID-only view with the full table:

$ docker history --quiet IMAGE_NAME:TAG
IMAGE_ID
IMAGE_ID
IMAGE_ID

--quiet prints only image IDs, one per history entry. It is useful when another script needs identifiers rather than human-readable text. It is not a count of files or containers.

4. Make a stable report with --format

For scripts and small reports, select fields explicitly with a Go template. This example prints the ID, creation time and recorded command separated by tabs:

$ docker history --no-trunc --format '{{.ID}}\t{{.CreatedAt}}\t{{.CreatedBy}}' IMAGE_NAME:TAG
IMAGE_ID	2026-09-23 05:00:00 +0000 UTC	/bin/sh -c ...

The available history fields include .ID, .CreatedSince, .CreatedAt, .CreatedBy, .Size and .Comment. The shell quotes keep the template together as one argument. Keep that quoting when adding pipes or redirects:

$ docker history --format '{{.ID}} {{.Size}} {{.Comment}}' IMAGE_NAME:TAG > image-history.txt

The file is created or replaced by the shell. That is the only state-changing part of this example, and it changes a file in your current directory. Choose an output path carefully if an existing report matters. To undo it, remove that specific report after checking it is the file you intended to create:

$ rm -- image-history.txt

Warning: Do not pass untrusted text as a template or image reference without understanding shell quoting. A template is interpreted by Docker's formatting system, while command substitution and redirection are interpreted by your shell.

5. Inspect one platform variant

When a local image has several platform variants, use --platform with an operating system and optional architecture and variant:

$ docker history --platform linux/amd64 IMAGE_NAME:TAG
IMAGE        CREATED       CREATED BY                         SIZE      COMMENT
IMAGE_ID     ...           /bin/sh -c ...                     ...       ...

For example, valid shapes include linux/amd64 and linux/arm64/v8. Without this option, Docker uses the daemon's native platform where available, otherwise the first available one. The requested variant must exist in the local image cache; this command does not fetch it.

If the variant is absent, Docker returns an error rather than silently showing another platform. Pulling an image for a platform is a separate operation and can download data, so confirm the registry, tag and disk space before doing that. No elevated privilege is required by docker history itself, although the daemon's access policy still applies.

6. Handle the common traps

Done means