Docker Image Config Viewer

Read what is in an image without running it. Everything here is visible to anybody who can pull the image, which is the point of looking.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Read. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A token in the environment

Reported by name only, and readable by anybody who can pull the image

{
  "config": {
    "User": "app",
    "Env": ["PATH=/usr/bin", "NPM_TOKEN=REPLACE_ME"]
  },
  "rootfs": { "diff_ids": ["sha256:aaa"] }
}

An empty User

Which means root, not a default user

{
  "config": { "User": "", "Env": [] },
  "rootfs": { "diff_ids": ["sha256:aaa"] }
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Putting a credential in an ENV because the image is private

    Private means fewer people can pull it, not none. Everybody who can pull can read the config, and the value is also in every container's environment.

    Instead:Pass it at run time, or use a build secret mount if it is only needed during the build.

  2. Comparing diff_ids to the manifest's layer digests

    One is uncompressed and the other compressed, so they never match. It looks exactly like a tampered image.

    Instead:Compare diff_ids with diff_ids and manifest digests with manifest digests.

  3. Leaving User unset because the app does not need root

    An unset User is root. The container runs as root whether or not the application wants to.

    Instead:Add a USER instruction after the steps that need write access to system paths.

The image config is not private

docker inspect shows it without starting a container, and a plain registry GET of the config blob shows it to anybody with pull access. There is no such thing as a secret in here.

Env is readable by everyone who can pull

Every variable and every value. There is no instruction that removes one, because the config records the final state rather than the sequence. A credential in an ENV is a published credential, and rebuilding does not un-publish an image already pushed.

diff_ids never match the manifest's layer digests

A diff_id is the digest of the uncompressed layer tar; a manifest layer digest is the digest of the compressed blob. They describe the same layer through different bytes. Comparing them to verify an image always fails and always looks like tampering, which is a very convincing false alarm.

An empty User means root

Not a default user, not nobody: root. Anything the process can reach on a mounted volume it reaches as root on the host's filesystem, and a container escape starts from a much better position.

history records every build step, including the arguments

docker history reads exactly this array. A build argument's value is recorded here whether or not the file it wrote survived, which is why deleting the file in a later layer does not help.

empty_layer marks metadata-only steps

ENV, LABEL, EXPOSE and similar change the config without producing a layer. They still appear in the history, so the number of history entries is not the number of layers.

What this cannot see

The layer contents. It reads the config, in your browser, and prints environment NAMES only, never values.