We are thrilled to announce 📢 Kosli is now SOC 2 Type 2 compliant - Read more
New Feature: Kosli Trails is liveCreate comprehensive audit trails for any DevOps activity - Read more
docker inspect

Docker Inspect Explained: The Essential Guide

Bruce Johnston
Published February 13, 2023 in technology
clock icon 9 min read

These days, it’s hard for a software engineer to go about their work without bumping into a Docker container. But when we bump into one that’s behaving oddly, how do we go about finding out more about it? That depends on the information we want and we can use the inspect command to get it.  

  • Inspect configuration—Find out about the base image, volume mounts, port mappings, etc. Use the Docker inspect command.
  • Inspect files—The exec command can get you into an interactive shell prompt where you can run commands and inspect files. Or you can save the image as a tar archive and inspect that archive.

In this post, we’ll take a look at the inspect command that allows us to inspect the configuration of various Docker objects. 

=Discover how Kosli allows you to follow a source code change to Docker runtime environments

Learn how to track changes with Kosli

Docker Inspect Syntax

The syntax of the command is

$ docker inspect [OPTIONS] NAME|ID [NAME|ID...]

It seems that we can inspect multiple objects identified by their name or ID. But what type of objects? While the official Docker documentation is not specific about this, we can inspect most of the Docker objects that are available. What are those? If we simply run the Docker command, we can see the available types under “Management commands” in the output. For example, config, container, context, image, manifest, network, node, plugin, secret, service, stack, and volume are all types. For most of these, we can also do a

$ docker <type> ls

such as “docker node ls,” to display all nodes. We can get the IDs of these objects in the ls listing and pass them to the Docker inspect command to get more information. Many of these types have a Docker command for themselves that supports an inspect action, e.g., Docker container inspect, Docker volume inspect, etc. However, this allows us to inspect only objects of that type, whereas the inspect command can accept different types of objects in one go. Now, let’s look at the options.

Options

  • Format, -f: Format the output using the given Go template. Since Docker was written in the language, it’s natural that the formatting features of that language are used.
  • Size, -s: Display the total file sizes if the type is container.
  • Type: This represents the type of Docker object that we want to inspect.

Now that we’ve taken a look at the syntax, let’s go through some examples of usage. The default format of the output is JSON, but we can customize the formatting by using the -f option.

Examples

The default, if we don’t specify the formatting, is to output the entire JSON. If we want to inspect the mysql image

$ docker inspect mysql

the output will be something like this:

[
  {
    "Id": "sha256:b05128b000ddbafb0a0d2713086c6a1cc23280dee3529d37f03c98c97c8cf1ed",
    "RepoTags": [
      "mysql:latest"
    ],
    "RepoDigests": [
      "mysql@sha256:aeecae58035f3868bf4f00e5fc623630d8b438db9d05f4d8c6538deb14d4c31b"
    ],
    "Parent": "",
...

It’s not necessary to specify the type option unless the object name is ambiguous. Docker figures out its type. If we want to extract some specific pieces of data rather than the entire JSON, then we need to use the formatting option. For that, a study of Go’s templating functionality will stand us in good stead. Let’s say we wanted the base image, the volume mounts, and the command run on the container initialization. We could do a

$ docker inspect mysql -f "{{.RepoTags}},  {{.Config.Volumes}}, {{.Config.Cmd}}"

and the output would be something like this:

[mysql:latest],  map[/var/lib/mysql:{}], [mysqld]

Docker passes the resulting config object to the template, and then the template invokes methods on that object, e.g., {{.RepoTags}} will access the RepoTags data. The {{}} tells the parser that there’s some data inside that needs to be evaluated and then substituted into the template output. We can also nest the calls, e.g., {{.Config.Volumes}} accesses the volumes object under the config object, and so on. It’s also possible to use Go’s built-in functions on the data. For instance, in the above example, RepoTags returns an array since there can be many. To get just the first entry, we can use Go’s index function with an argument of 0.

$ docker inspect mysql -f "{{index .RepoTags 0}}"

The output will just be the first element. The JSON output will differ based on what type of object we’re inspecting. A container, for instance, will have stuff like state, HostConfig, and NetworkSettings, while an image won’t. Also, the output can change depending on the state of the object. For example, let’s inspect the ports under NetworkSettings, which are available only for a running container.

$ docker inspect --format='{{.NetworkSettings.Ports}}' <container-id>

The output is

map[80/tcp:[{0.0.0.0 8080}]]

This is a map of key values, where the container port is the key and the value is an array of host ports to which we have bound. Let’s try using Go’s range function to iterate over the port-mappings:

$ docker inspect --format='{{range $contPort, $hostPorts := .NetworkSettings.Ports}} {{$contPort}} -> {{(index $hostPorts 0).HostPort}} {{end}}' <container-id>

A map is a collection of key value pairs. The range function allows us to iterate over collections. We’re assigning the key to $confPort and the value to $hostPorts. Then, we can print the container port and the first (index 0) host-port mapped to it. Note how we get just the port number by using .HostPort. The output looks like this:

80/tcp -> 8080

But how did we know that the host-port data has something called HostPort when the output of inspecting ports above didn’t show it? It seems that the output when using the format option is as per Go’s default formatting and may be abridged, i.e., doesn’t display the full JSON. However, if we print the entire JSON with a

$ docker inspect <container-id>

or the other form of the inspect as an action of the container command

$ docker container inspect <container-id>

and look at the ports section, it shows something like this:

  "Ports": {
                "80/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "8080"
                    }
                ]
            },

So, we should inspect the entire JSON without the format option for a better understanding of the schema/structure. Let’s see how the formatting template supports if-else conditions. When we want to check if the object to be inspected is a container or not, use

$ docker inspect --format='{{ if and (index . "Image") (index . "State")}} Its a container {{else}} Its not a container{{end}}' <object-id>

The above code will print “Its a container” if the inspected object is a container, or it will print “Its not a container” if not. Unfortunately, the inspect output doesn’t have a type attribute to say what type it is, so we’ve used some criteria of our own. We’re checking if the “State” and “Image” values are present. Just checking for “if .State” will throw an exception about a key not being in the map if we inspect a non-container object, e.g., a volume. So we use the index function to check if a particular value exists in a map. Note the use of “.” to refer to the top-level config object.

Also, since “and” is a function here and not an operator, it comes before rather than between the two conditions. What if we wanted to output the port-mappings of all running containers? We saw earlier how to do this for a single container. We also know that the inspect command supports multiple object ID/names as input. So somehow we need to pass all the container IDs to the inspect command. We can do this using a shell facility called command substitution, where the output of one command can be inserted as parameters to another command. This is different from the pipe(|), which streams the output of one command as input data to another. So, how do we get a list of all container IDs? Try this:

$ docker ps -q

The -q option tells the command to print only the container IDs. With the previous example and command substitution, our command line becomes

$ docker inspect --format='{{range $contPort, $hostPorts := .NetworkSettings.Ports}} {{$contPort}} -> {{(index $hostPorts 0).HostPort}} {{end}}' 
`docker ps -q`

The backquotes are used for command substitution. Note that if there are no running containers, you might get an error that says “docker inspect requires at least 1 argument,” since the Docker ps command generated no container IDs.

Conclusion

We can use the inspect command to get low-level configuration information about various Docker objects like images, containers, volumes, networks, nodes, etc., to see, for example, on which node a container is deployed or what ports it listens to. It allows us to inspect multiple objects of different types in one go. The default output format is JSON, but the formatting option can be used to generate output in the way we want. Using the command substitution facility of the shell along with the inspect command can make it even more powerful.

FAQ

How do I examine the files within a Docker image using “docker inspect”?

You can’t, because docker inspect is used for inspecting containers and their configurations. To examine the files within an image, you would typically need to run a container from the image and then use commands like docker exec or docker run to access and examine the files within the running container.

How to get IP from docker inspect?

To retrieve the IP address of a Docker container using docker inspect, you can use the –format option to extract the IP address from the network settings.

How can I inspect the network settings of a Docker container with “docker inspect”? To inspect the network settings of a Docker container, you can use the docker inspect command with a specific format for network details.

What is the purpose of the “–format” option in “docker inspect”?

The –format option in the docker inspect command allows you to specify a Go template to format the output. It’s useful for customizing the information you want to retrieve about a container.

How can I use Docker inspect to get details of a container?

To get details of a Docker container, you can use the docker inspect command followed by the container’s ID or name. Ex. docker inspect <container_name_or_id>

=Discover how Kosli allows you to follow a source code change to Docker runtime environments

Learn how to track changes with Kosli

ABOUT THIS ARTICLE

Published February 13, 2023, in technology

AUTHOR

Stay in the loop with the Kosli newsletter

Get the latest updates, tutorials, news and more, delivered right to your inbox
Kosli is committed to protecting and respecting your privacy. By submitting this newsletter request, I consent to Kosli sending me marketing communications via email. I may opt out at any time. For information about our privacy practices, please visit Kosli's privacy policy.
Kosli team reading the newsletter

Got a question about Kosli?

We’re here to help, our customers range from larges fintechs, medtechs and regulated business all looking to streamline their DevOps audit trails

Contact us
Developers using Kosli