Docker Inspect Template Magic



Most Docker users are aware of the docker inspect command which is used to get metadata on a container or image, and may have used the -f argument to pull out some specific data, for example using docker inspect -f {{.IPAddress}} to get a container’s IP Address. However, a lot of users seem confused by the syntax of this feature and very few people take full advantage of it (most people seem to pipe the output through grep, which is effective but messy). In this post, I’ll look into how the -f argument works and show some examples of how to use it.

Put simply, the -f argument takes a Go template as input and runs it against the metadata for the given containers or images. The first problem is the phrase “Go template” is rather nebulous, at least to anyone inexperienced in Go — my first feeling was atavistic fear from the memory of C++ templates. Thankfully, Go templates has nothing in common with C++ templates or generics, and is in fact a template engine that takes a data source and a template pattern and combines the two to produce an output document. This idea should be very familiar to most web developers and common examples of template engines include Jinga2 (commonly used with Python and Flask), Mustache and JavaServer Pages. The concept is perhaps best explained by a simple example:

As we can see, the argument to -f is a simple pattern (or template) that we want to apply to the metadata of container. In fact, we don’t even have to do anything with the metadata:

But, if we learn a bit of Go templating magic, things that were once tricky become much simpler. For example, to find the names of all containers with a non-zero exit code:

(Unfortunately Docker prints a new-line for each container, whether it matches the if or not).

Or to find the host directory for the volume /var/jenkins_home in my jenkins-data container:

At the moment, both of these examples are probably a little hard to parse. There are a few basics you need to understand before you can get started with your own templates.


The {{ }} syntax is used for processing directives. Anything outside of the curly brackets will be output literally.

The . Context

A “.” stands for the “current context”. Most of the time this is the whole data structure for the metadata of the container, but it can be rebound in certain cirumstances, including using the with action:

You can always get the root context by using $. e.g.

Note that it is perfectly valid to use a “.” by itself, the following will just output the full data completely unformatted:

Data Types

The inspect data seems to consist of floats, strings and booleans. These can be tested and compared using various functions. At the moment, it seems that all numbers are floats, although Go templates do support integers, which would seem to be more appropriate in most cases (I’ve submitted an issue about this). Use double quotes when working with strings.

Values which appear as “null” appear to be not present in the data at all, and can’t be compared:

Data Structures

The inspect data uses maps and arrays. Maps are normally easy, you can just chain stuff together to access inner maps as we’ve seen already:

However, this isn’t possible if the key for the map isn’t in a suitable format (for example, if it uses a non alphanumeric character). If that’s the case, you can use the index function as we did in the volumes example:

You can also use index to get an array entry by number:


Apart from index, there are a few more functions that are likely to be useful. The logical functions and, or and not are available and operate largely as expected, returning a boolean result. Note that as they are functions, they cannot be used infix i.e:


The following comparison functions are available:

  • eq (equals)
  • ne (not eqaul)
  • lt (less than)
  • le (less than or equal to)
  • gt (greater than)
  • ge (greater than or equal to)

They can compare strings, floats or integers:

But note that output types have to match, and numbers in Docker seem to be all floats, despite how they are printed:

UPDATE: This seems to have been fixed; now both integers and floats will work correctly e.g:

(This was tested in Docker 1.7).

There is also a json function for generating JSON:

So you can combine templates with the jq tool, which you may be more familiar with:


Of course, the default output of docker inspect is also JSON, so this also works:


There are a few more functions listed in the official Go documentation, but it weirdly seems to be missing the json function (which I learnt from Nathan LeClaire’s blog) — if someone knows the reason for this, please let me know!

If Statements

Conditional statements can be handled with an if statement and normally use one of the previous comparison functions:

Note the {{end}} statement is required to terminate the if. The else if and else parts are optional.


I think this covers most of the stuff you are likely to need when using templates with docker inspect, but there are more features available, such as using range to iterate over data, defining your own functions and using pipes.

I have yet to find a good, complete reference to using Go templates. The best I have found so far is a chapter from a the free e-book “Network programming with Go” by Jan Newmarch.

There is also the official Go documentation, but it is little terse and hard to follow, especially if you’re not a Go programmer.


    • Any idea on how to get the last element of Config.Env ?

      I can get the whole list, the first element, the second, the length of the array, but have tried various syntaxes looking, like len-1
      , to no avail.

      $ docker inspect -f ‘{{ .Config.Env }}’ 7a7
      [DISPLAY=:0 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LANG=fr_FR.UTF-8 LANGUAGE=fr_FR:en LC_ALL=fr_FR.UTF-8 DEBIAN_FRONTEND=noninteractive HOME=/home/gg WINEARCH=win32 WINEPREFIX=/home/gg/.wine_captvty]
      $ docker inspect -f ‘{{ index ( .Config.Env) 0 }}’ 7a7
      $ docker inspect -f ‘{{ index ( .Config.Env) 1 }}’ 7a7
      $ docker inspect -f ‘{{ len .Config.Env }}’ 7a7

      Thanks for this great tutorial

  1. @Labadie

    I’m glad you found the post useful.

    There are no maths functions defined by default in templates, so you can’t do +, – or even inc or dec. I think you might be able to solve your problem using range, but it would be a bit messy (the solution that springs to mind is iterating through the array, saving the current value in a variable until you come to the last value, when you print the previous value).


  2. Jérôme Petazzoni tweeted a solution for this, thanks to him

    docker inspect –format “{{ index .Config.Cmd $[$(docker inspect –format ‘{{ len .Config.Cmd }}’ $CID)-1]}}” $CID

    • Ha, excellent. I didn’t think of embedded inspects, which of course lets you use bash to do maths. Thanks for updating this with the answer.

  3. I really like this example page!!!

    A range example would be very helpful.

    Here’s my example:

    I want to list all named volumes mounted in a container (docker volumes created using the docker volume create command.)

    docker inspect --format '{{range .Mounts}} {{ .Name }} {{end}}' jenkins

    Now let’s say I want to list every named volume from every container

    docker inspect --format '{{range .Mounts}} {{ .Name }} {{end}}' $(docker ps -aq)

    But now I’m left with a long list and I don’t know which volume goes with which container. Now I need to use a variable to remember the container name and print it

    docker inspect --format '{{$x:=.Name}} {{range .Mounts}} {{$x}}@{{ .Name }} {{end}}' $(docker ps -aq)

    This is great and all, but all the non-named volumes caused extra $x@ to get printed… In this particular case, only named volumes have a Name field in .Mounts, so I was able to use an if statement (already covered) to

    docker inspect --format '{{$x:=.Name}} {{range .Mounts}} {{if .Name}} {{$x}}@{{ .Name }} {{end}} {{end}}' $(docker ps -aq)

    And I have exactly what I wanted!

    A little bash candy coating, and I have a “find which docker has this named volume mounted” function

    function dc_find_volume()
    local volumes=($(docker inspect --format '{{$x:=.Name}} {{range .Mounts}} {{if .Name}} {{$x}}@{{ .Name }} {{end}} {{end}}' $(docker ps -aq)))
    local x
    for x in "${volumes[@]}"; do
    if [[ ${x} =~ .*@$1 ]]; then
    echo ${x%@*}

    Note: I was not able to get example 2 ( working in docker

  4. Hi Thanks for the notes I have a doubt
    I know only my docker container name and i want to get containers host port i tried
    docker inspect –format ‘{{ (index (index .NetworkSettings.Ports “1500/tcp”) 0).HostPort }}’ container_name
    it works but i gave the Hostport also so that i don’t want this kind of format use container name if there is any possible please help me..


  5. Hi guys,

    Just sharing how to extract the marathon app id:

    docker inspect -f “{{range .Config.Env}}{{ if eq (index (split . \”=\”) 0) \”MARATHON_APP_ID\”}}{{(index (split . \”=\”) 1)}}{{end}}{{end}}” 3ee7ac120b48

  6. Thank you for the intro ! It was very helpful!

    I used it to get a template for docker ps where ports are shown on a line each by adding this in the ~/.docker/config.json

    “psFormat”: “table {{.Names}}\\t{{.Image}}\\t{{.RunningFor}}\\t{{.Status}}\\n{{range (split .Ports \”, \”)}}\\t{{println .}}{{end}}”

  7. Range example. Displays Docker Client Version and Docker Server Version

    docker version –format ‘{{println .Client.Version}}{{range .Server.Components}}{{if eq .Name “Engine”}}{{.Version}}{{- end}}{{else}}{{end}}’

Leave a Reply

Your email address will not be published. Required fields are marked *