Skip to content

Instantly share code, notes, and snippets.

@efrecon
Last active May 23, 2024 15:21
Show Gist options
  • Save efrecon/8ce9c75d518b6eb863f667442d7bc679 to your computer and use it in GitHub Desktop.
Save efrecon/8ce9c75d518b6eb863f667442d7bc679 to your computer and use it in GitHub Desktop.
`docker inspect` template to regenerate the `docker run` command that created a container
docker run \
--name {{printf "%q" .Name}} \
{{- with .HostConfig}}
{{- if .Privileged}}
--privileged \
{{- end}}
{{- if .AutoRemove}}
--rm \
{{- end}}
{{- if .Runtime}}
--runtime {{printf "%q" .Runtime}} \
{{- end}}
{{- range $b := .Binds}}
--volume {{printf "%q" $b}} \
{{- end}}
{{- range $v := .VolumesFrom}}
--volumes-from {{printf "%q" $v}} \
{{- end}}
{{- range $l := .Links}}
--link {{printf "%q" $l}} \
{{- end}}
{{- if index . "Mounts"}}
{{- range $m := .Mounts}}
--mount type={{.Type}}
{{- if $s := index $m "Source"}},source={{$s}}{{- end}}
{{- if $t := index $m "Target"}},destination={{$t}}{{- end}}
{{- if index $m "ReadOnly"}},readonly{{- end}}
{{- if $vo := index $m "VolumeOptions"}}
{{- range $i, $v := $vo.Labels}}
{{- printf ",volume-label=%s=%s" $i $v}}
{{- end}}
{{- if $dc := index $vo "DriverConfig" }}
{{- if $n := index $dc "Name" }}
{{- printf ",volume-driver=%s" $n}}
{{- end}}
{{- range $i, $v := $dc.Options}}
{{- printf ",volume-opt=%s=%s" $i $v}}
{{- end}}
{{- end}}
{{- end}}
{{- if $bo := index $m "BindOptions"}}
{{- if $p := index $bo "Propagation" }}
{{- printf ",bind-propagation=%s" $p}}
{{- end}}
{{- end}} \
{{- end}}
{{- end}}
{{- if .PublishAllPorts}}
--publish-all \
{{- end}}
{{- if .UTSMode}}
--uts {{printf "%q" .UTSMode}} \
{{- end}}
{{- with .LogConfig}}
--log-driver {{printf "%q" .Type}} \
{{- range $o, $v := .Config}}
--log-opt {{$o}}={{printf "%q" $v}} \
{{- end}}
{{- end}}
{{- with .RestartPolicy}}
--restart "{{.Name -}}
{{- if eq .Name "on-failure"}}:{{.MaximumRetryCount}}
{{- end}}" \
{{- end}}
{{- range $e := .ExtraHosts}}
--add-host {{printf "%q" $e}} \
{{- end}}
{{- range $v := .CapAdd}}
--cap-add {{printf "%q" $v}} \
{{- end}}
{{- range $v := .CapDrop}}
--cap-drop {{printf "%q" $v}} \
{{- end}}
{{- range $d := .Devices}}
--device {{printf "%q" (index $d).PathOnHost}}:{{printf "%q" (index $d).PathInContainer}}:{{(index $d).CgroupPermissions}} \
{{- end}}
{{- end}}
{{- with .NetworkSettings -}}
{{- range $p, $conf := .Ports}}
{{- with $conf}}
--publish "
{{- if $h := (index $conf 0).HostIp}}{{$h}}:
{{- end}}
{{- (index $conf 0).HostPort}}:{{$p}}" \
{{- end}}
{{- end}}
{{- range $n, $conf := .Networks}}
{{- with $conf}}
--network {{printf "%q" $n}} \
{{- range $a := $conf.Aliases}}
--network-alias {{printf "%q" $a}} \
{{- end}}
{{- end}}
{{- end}}
{{- end}}
{{- with .Config}}
{{- if .Hostname}}
--hostname {{printf "%q" .Hostname}} \
{{- end}}
{{- if .Domainname}}
--domainname {{printf "%q" .Domainname}} \
{{- end}}
{{- if index . "ExposedPorts"}}
{{- range $p, $conf := .ExposedPorts}}
--expose {{printf "%q" $p}} \
{{- end}}
{{- end}}
{{- if .User}}
--user {{printf "%q" .User}} \
{{- end}}
{{- range $e := .Env}}
--env {{printf "%q" $e}} \
{{- end}}
{{- range $l, $v := .Labels}}
--label {{printf "%q" $l}}={{printf "%q" $v}} \
{{- end}}
{{- if not (or .AttachStdin (or .AttachStdout .AttachStderr))}}
--detach \
{{- end}}
{{- if .AttachStdin}}
--attach stdin \
{{- end}}
{{- if .AttachStdout}}
--attach stdout \
{{- end}}
{{- if .AttachStderr}}
--attach stderr \
{{- end}}
{{- if .Tty}}
--tty \
{{- end}}
{{- if .OpenStdin}}
--interactive \
{{- end}}
{{- if .Entrypoint}}
{{- /* Since the entry point cannot be overridden from the command line with an array of size over 1,
we are fine assuming the default value in such a case. */ -}}
{{- if eq (len .Entrypoint) 1 }}
--entrypoint "
{{- range $i, $v := .Entrypoint}}
{{- if $i}} {{end}}
{{- $v}}
{{- end}}" \
{{- end}}
{{- end}}
{{printf "%q" .Image}} \
{{range .Cmd}}{{printf "%q " .}}{{- end}}
{{- end}}
@oparin-alexander
Copy link

I had the same issue
Template parsing error: template: :19:18: executing "" at <.Mounts>: map has no entry for key "Mounts"
Docker version is Docker version 1.13.1, build 7d71120/1.13.1

In my version .Mounts is located in the root of docker inspect. Something like that:

[
    {
        "HostConfig": {
        ...
        },
        "Mounts": [
            {
                "Type": "bind",
                "Source": "example",
                "Destination": "example",
                "Mode": "rw",
                "RW": true,
                "Propagation": "rprivate"
            },
            ...
        ],
        ...
    }
]

So moving

          {{- range .Mounts}}
  --mount type={{.Type}},source={{.Source}},destination={{.Destination}}{{- if .Propagation}},bind-propagation={{.Propagation}}{{- end}}{{- if not .RW}},readonly{{- end}} \
        {{- end}}

out of .HostConfig scope has helped me

@ictus4u
Copy link

ictus4u commented Feb 6, 2023

Hi @efrecon , I'd be pleased if you'd review my just-added support for --mount: https://gist.github.com/ictus4u/e28b47dc826644412629093d5c9185be .

@oparin-alexander I've seen two .Mounts, one inside the HostConfig and the other outside, as you noticed. After some play around, I've found the outer is the effective configuration. But the inner is reflecting the specified --mount options, thus, likely this is the one we want to reverse engineer to get the generating command.

@matheusyl probably in your container the --mount command was not used, so the .Mounts config was not found. In my current proposal, I consider that case and check if it exists before the loop.

@griloHBG Thank you for pushing it forward.

@efrecon
Copy link
Author

efrecon commented Feb 10, 2023

@ictus4u You are right, there are two .Mounts. The one inside HostConfig seems to reflect what you provided at the command-line (or docker compose, or ...) and is the one that we want to work with I think. For example, if you use secrets, they will also appear there (marked as read only). I have tried to fix with an extra "if" to see if that helps. @matheusyl can you check if the new version fixes your problems?

@MarcelloPercoco
Copy link

@ictus4u You are right, there are two .Mounts. The one inside HostConfig seems to reflect what you provided at the command-line (or docker compose, or ...) and is the one that we want to work with I think. For example, if you use secrets, they will also appear there (marked as read only). I have tried to fix with an extra "if" to see if that helps. @matheusyl can you check if the new version fixes your problems?

Hi.

I'm facing the exact same problem, and the last update dosen't seem to have fixed it; i see those errors and some run file are still empty

Thanks and best regards

@donny-son
Copy link

For those who are restricted to public internet access can use cat instead of curl.

docker inspect --format "$(cat /path_to_file/run.tpl)" name_or_id_of_running_container

@uvlad7
Copy link

uvlad7 commented May 10, 2023

Please add

--user {{.Config.User}}

@QGB
Copy link

QGB commented May 16, 2023

docker inspect --format "$(curl -s https://gist.githubusercontent.com/efrecon/8ce9c75d518b6eb863f667442d7bc679/raw/run.tpl)" ded0bdd038e4

Template parsing error: template: :22:15: executing "" at <.Mounts>: map has no entry for key "Mounts"

@efrecon
Copy link
Author

efrecon commented May 16, 2023

@uvlad7 --user now supported. @QGB try again, I have merged and adapted the changes from @ictus4u

@htjain
Copy link

htjain commented Jun 5, 2023

docker inspect --format "$(curl -s https://gist.githubusercontent.com/efrecon/8ce9c75d518b6eb863f667442d7bc679/raw/run.tpl)" ded0bdd038e4

Template parsing error: template: :22:15: executing "" at <.Mounts>: map has no entry for key "Mounts"

Same error

@saschabrockel
Copy link

Thank you for the great work! Unfortunately, I recognized that everything regarding health checks is missing:

  --health-cmd="redis-cli
  --raw incr ping"
  --health-interval=30s
  --health-timeout=10s
  --health-retries=3

Would it be possible to add them too?

@xuganyu96
Copy link

This is fantastically simple and effective. Thank you so much!

@snowdream
Copy link

thank you so much!

@SimonWoidig
Copy link

Starred! Simply amazing!

@yousri666
Copy link

great work! so helpful

@insinfo
Copy link

insinfo commented May 6, 2024

great work! so helpful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment