It is common to think of Docker images and containers as mystical black boxes where all the application goodness gets locked away. Fortunately, there is a way to unlock both structures using the docker inspect command. Inspect is a core Docker instruction with detailed documentation. However, there is little information about interpreting the output. This article will explain running docker inspect and detailing the results.

How to inspect

Every Docker command has built in documentation. Typing docker inspect --help will generate the following help documentation.

Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]

Return low-level information on a container or image

    -f, --format=    Format the output using the given go template
    --help=false     Print usage

Running Inspect

Based on the help output, the inspect command can be run on one or more images or containers. Either the name or id can be used to identify an image or container, and by using docker images a list of local images can be found.

REPOSITORY               TAG        IMAGE ID        CREATED       VIRTUAL SIZE
centurylink/watchtower   latest     f76c0f6b907f    5 days ago    5.871 MB
centurylink/panamax-api  latest     9f00b0d73e96    7 weeks ago   93.58 MB

For images the Repository name or the Image ID can be used to identify the images. Using the results above a valid inspect command could be the following:

docker inspect f76c0f6b907f
docker inspect centurylink/watchtower

The ps command by default shows only running containers but passing the -a flag to the command will show all containers.

CONTAINER ID    IMAGE                    COMMAND         CREATED       STATUS PORTS NAMES
c9e23ca73a66    centurylink/watchtower   "/watchtower"   4 days ago    Up 4 days
watchtower
2ff6adf54f4a    centurylink/watchtower   "/watchtower"   4 days ago    Exited (1) 4 days ago cocky_bohr

Containers have both a name and identifier either can be used to identify the container to inspect. Using the results above, valid inspect commands could be:

docker inspect c9e23ca73a66
docker inspect cocky_bohr

All of the previous examples only inspected a single item but it is possible to inspect multiple combinations of images and/or containers in a single command.

docker inspect cocky_bohr c9e23ca73a66
docker inspect centurylink/watchtower f76c0f6b907f
docker inspect f76c0f6b907f centurylink/watchtower cocky_bohr

The last example above mixes images and containers in the same result which is valid.

Formatting Results

One of the options for inspect is the format option. This allows the results to be filtered on a specific stanza of the inspection result. This format string follows go templating which may require some additional learning to use in detail but in general it's pretty easy to get the information you need from the results. For example, passing '{{.NetworkSettings.IPAddress}}' will return just the ip address which is 172.17.0.3 for the watchtower container.

docker inspect -f '{{.NetworkSettings.IPAddress}}' watchtower
172.17.0.3

Results can be filtered using the standard grep tool as well.

docker inspect watchtower | grep IPAddress
    "IPAddress": "172.17.0.3",
    "SecondaryIPAddresses": null,

While not as precise the IPAddress is present. However, for some data structures in the result, a simple grep is not sufficient. Let's try to get all of the NetworkSettings using grep.

docker inspect watchtower | grep NetworkSettings
        "NetworkSettings": {

Since grep is a text based tool it returns the line where "NetworkSettings" occurs but in this case its not very helpful. Using the -f option, however, will return much better results as shown in the example below.

docker inspect -f '{{.NetworkSettings}}' watchtower
{ bf2db906cf18b35540c110653200e52c00f8f42b9709bd6095037abb993ec179
172.17.42.1 0 false 172.17.0.3 16 0 02:42:ac:11:00:03
34cd76d0b7493bb5a11045efc0bae93e289e45d9a47fb075eaf567598d7c4a6b
map[] map[] /var/run/docker/netns/c9e23ca73a66 [] []}

Inspecting Images

The results of inspecting an image differ from the results of inspecting a container. Most of the elements are pretty easy to understand but a few of them may not be as obvious.

$ docker inspect centurylink/watchtower
    [
    {
        "Id":
    "f76c0f6b907fd796e744f0def3557b5126239a48f0979bdba4b838b6d711ebeb",
        "Parent":
    "72fb015ccc1ae0a1a40e727660894a16674eabb034f3127678c21d6df0b633d9",
        "Comment": "",
        "Created": "2015-08-04T18:00:30.345767062Z",
        "Container":
    "dacb392a5cdd41c45b177b767e8b713d04889f63faafec4818ba9118df145a10",
        "ContainerConfig": {
            "Hostname": "e30253796536",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "PortSpecs": null,
            "ExposedPorts": null,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [

    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ENTRYPOINT [\"/watchtower\"]"
            ],
            "Image":
    "72fb015ccc1ae0a1a40e727660894a16674eabb034f3127678c21d6df0b633d9",
            "Volumes": null,
            "VolumeDriver": "",
            "WorkingDir": "",
            "Entrypoint": [
                "/watchtower"
            ],
            "NetworkDisabled": false,
            "MacAddress": "",
            "OnBuild": [],
            "Labels": {
                "com.centurylinklabs.watchtower": "true"
            }
        },
        "DockerVersion": "1.6.2-circleci",
        "Author": "CenturyLink Labs \[email protected]\u003e",
        "Config": {
            "Hostname": "e30253796536",
            "Domainname": "",
            "User": "", "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "PortSpecs": null,
            "ExposedPorts": null,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [

    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ], "Cmd": null,
            "Image": "72fb015ccc1ae0a1a40e727660894a16674eabb034f3127678c21d6df0b633d9",
            "Volumes": null,
            "VolumeDriver": "",
            "WorkingDir": "",
            "Entrypoint": [
                "/watchtower"
            ],
            "NetworkDisabled": false,
            "MacAddress": "",
            "OnBuild": [],
            "Labels": {
                "com.centurylinklabs.watchtower": "true"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 0,
        "VirtualSize": 5871467
    }
    ]

Interesting Image Inspect Results

  • ID This is the unique identifier of the image.

  • Parent A link to the identifier of the parent image. It is very common for an image to have a defined parent.

  • Container A container identifier is interesting because this is meta-data for an image not a container. This container identifier is a temporary container created when the image was built. Docker will create a container during the image construction process, and this identifier is stored in the image data.

  • ContainerConfig This data again is referring to the temporary container created when the Docker build command was executed.

  • DockerVersion The version of Docker used to create the image is stored in this value. It could be very useful as the Docker ecosystem continues to advance.

  • Virtual Size The size of the image reported in bytes.

Inspecting Containers

The results from inspecting a container have very different options. The container is the runtime environment for the image, so the meta-data for containers must provide all of the runtime configurations needed to start and restart the image with all of its settings intact.

$docker inspect watchtower
[
{
    "Id":
"c9e23ca73a66365acc8d42714d4aae22c5e1dfc0dc079ad4366eb8dba8336f86",
    "Created": "2015-08-05T16:18:09.306673609Z",
    "Path": "/watchtower",
    "Args": [],
    "State": {
        "Running": true,
        "Paused": false,
        "Restarting": false,
        "OOMKilled": false,
        "Dead": false,
        "Pid": 3053,
        "ExitCode": 0,
        "Error": "",
        "StartedAt": "2015-08-05T16:18:09.374896026Z",
        "FinishedAt": "0001-01-01T00:00:00Z"
    },
    "Image":
"f76c0f6b907fd796e744f0def3557b5126239a48f0979bdba4b838b6d711ebeb",
    "NetworkSettings": {
        "Bridge": "",
        "EndpointID":
"bf2db906cf18b35540c110653200e52c00f8f42b9709bd6095037abb993ec179",
        "Gateway": "172.17.42.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "HairpinMode": false,
        "IPAddress": "172.17.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "MacAddress": "02:42:ac:11:00:03",
        "NetworkID":
"34cd76d0b7493bb5a11045efc0bae93e289e45d9a47fb075eaf567598d7c4a6b",
        "PortMapping": null,
        "Ports": {},
        "SandboxKey": "/var/run/docker/netns/c9e23ca73a66",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null
    },
    "ResolvConfPath":
"/mnt/sda1/var/lib/docker/containers/c9e23ca73a66365acc8d42714d4aae22c5e1dfc0dc
079ad4366eb8dba8336f86/resolv.conf",
    "HostnamePath":         "/mnt/sda1/var/lib/docker/containers/c9e23ca73a66365acc8d42714d4aae22c5e1dfc0dc079ad4366eb8dba8336f86/hostname",
    "HostsPath": "/mnt/sda1/var/lib/docker/containers/c9e23ca73a66365acc8d42714d4aae22c5e1dfc0dc079ad4366eb8dba8336f86/hosts",
    "LogPath": "/mnt/sda1/var/lib/docker/containers/c9e23ca73a66365acc8d42714d4aae22c5e1dfc0dc079ad4366eb8dba8336f86/c9e23ca73a66365acc8d42714d4aae22c5e1dfc0dc079ad4366eb8dba8336f86-json.log",
    "Name": "/watchtower",
    "RestartCount": 0,
    "Driver": "aufs",
    "ExecDriver": "native-0.2",
    "MountLabel": "",
    "ProcessLabel": "",
    "Volumes": {
        "/var/run/docker.sock": "/var/run/docker.sock"
    },
    "VolumesRW": {
        "/var/run/docker.sock": true
    },
    "AppArmorProfile": "",
    "ExecIDs": null,
    "HostConfig": {
        "Binds": [
            "/var/run/docker.sock:/var/run/docker.sock"
        ],
        "ContainerIDFile": "",
        "LxcConf": [],
        "Memory": 0,
        "MemorySwap": 0,
        "CpuShares": 0,
        "CpuPeriod": 0,
        "CpusetCpus": "",
        "CpusetMems": "",
        "CpuQuota": 0,
        "BlkioWeight": 0,
        "OomKillDisable": false,
        "Privileged": false,
        "PortBindings": {},
        "Links": null,
        "PublishAllPorts": false,
        "Dns": null,
        "DnsSearch": null,
        "ExtraHosts": null,
        "VolumesFrom": null,
        "Devices": [],
        "NetworkMode": "bridge",
        "IpcMode": "",
        "PidMode": "",
        "UTSMode": "",
        "CapAdd": null,
        "CapDrop": null,
        "RestartPolicy": {
            "Name": "no",
            "MaximumRetryCount": 0
        },
        "SecurityOpt": null,
        "ReadonlyRootfs": false,
        "Ulimits": null,
        "LogConfig": {
            "Type": "json-file",
            "Config": {}
        },
        "CgroupParent": ""
    },
    "Config": {
        "Hostname": "c9e23ca73a66",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "PortSpecs": null,
        "ExposedPorts": null,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": null,
        "Image": "centurylink/watchtower",
        "Volumes": null,
        "VolumeDriver": "",
        "WorkingDir": "",
        "Entrypoint": [
            "/watchtower"
        ],
        "NetworkDisabled": false,
        "MacAddress": "",
        "OnBuild": null,
        "Labels": {
            "com.centurylinklabs.watchtower": "true"
        }
    }
}
]

Interesting Container Inspect Results

  • ID The unique identifier for the container

  • State This stanza has various status flags and the process id for the container. Using the ExitCode from this State element a graceful shutdown or recovery process could be initiated. The following format will return just the ExitCode of the most recently run container:

    docker inspect -f '{{.State.ExitCode}}' $(docker ps -lq)
    
  • Image The image this container is running.

  • NetworkSettings The network environment for the container and therefore for the application(s) within the image.

  • LogPath The system path to this container's log file.

  • RestartCount Keeps track of the number of times the container has been restarted. This value is the key value used when defining a container's restart policy..

  • Name The user defined name for the container.

  • Volumes Defines the volume mapping between the host system and the container.

  • HostConfig Key configurations for how the container will interact with the host system. These could take CPU and memory limits, networking values, or device driver paths.

  • Config The runtime configuration options set when the docker run command was executed. Part of this configuration is another "Image" value. This image {{.Config.Image}} is the tagged image which may be different than the image listed in {{.Image}}

Summary

Docker images and containers are not the lock boxes many believe. Using the basic inspect command a wealth of information about images and/or containers can be gathered.

References