1、Inspect結果詳細信息
docker inspect 7988f914a122
其中7988f914a122是某一容器進程的id
{ "Id": "7988f914a122197035d687eebe0c9e31d69f84bb7b14d976a3fbb030d4d98f70", "Created": "2017-02-07T05:04:30.305563148Z", "Path": "/bin/bash", "Args": [], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 19138, "ExitCode": 0, "Error": "", "StartedAt": "2017-02-07T08:11:55.171653409Z", "FinishedAt": "2017-02-07T06:20:22.462071105Z" }, "Image": "sha256:93541fa8323099b6be585526fac694ac52063aba1830d6e1e9961594e43f8b88", "ResolvConfPath": "/var/lib/docker/containers/7988f914a122197035d687eebe0c9e31d69f84bb7b14d976a3fbb030d4d98f70/resolv.conf", "HostnamePath": "/var/lib/docker/containers/7988f914a122197035d687eebe0c9e31d69f84bb7b14d976a3fbb030d4d98f70/hostname", "HostsPath": "/var/lib/docker/containers/7988f914a122197035d687eebe0c9e31d69f84bb7b14d976a3fbb030d4d98f70/hosts", "LogPath": "/var/lib/docker/containers/7988f914a122197035d687eebe0c9e31d69f84bb7b14d976a3fbb030d4d98f70/7988f914a122197035d687eebe0c9e31d69f84bb7b14d976a3fbb030d4d98f70-json.log", "Name": "/newtomcat7", "RestartCount": 0, "Driver": "aufs", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": [ "/root/work/docker:/root/hzbtest" ], "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": { "5000/tcp": [ { "HostIp": "", "HostPort": "5000" } ] }, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": null, "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DiskQuota": 0, "KernelMemory": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": -1, "OomKillDisable": false, "PidsLimit": 0, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0 }, "GraphDriver": { "Name": "aufs", "Data": null }, "Mounts": [ { "Source": "/root/work/docker", "Destination": "/root/hzbtest", "Mode": "", "RW": true, "Propagation": "rprivate" } ], "Config": { "Hostname": "7988f914a122", "Domainname": "", "User": "", "AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "ExposedPorts": { "5000/tcp": {} }, "Tty": true, "OpenStdin": true, "StdinOnce": true, "Env": null, "Cmd": [ "/bin/bash" ], "Image": "93541fa83230", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "927b5aac94a952453bce87bbb346b3dd573f9af622c8913875ae564161ee3332", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "5000/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "5000" } ] }, "SandboxKey": "/var/run/docker/netns/927b5aac94a9", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "254ea67cfdda5bcafa3504141584f6c8148449f185574bcf1facd0a925416df9", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "4d1bed26364a6c5844e0530e77b37bbe637901ef0579930da6fba5e31484aa61", "EndpointID": "254ea67cfdda5bcafa3504141584f6c8148449f185574bcf1facd0a925416df9", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02" } } } }
很多 Docker 用戶都知道 docker inspect 命令,該命令用於獲取容器/鏡像的元數據,其中 -f 參數可以用於獲取指定的數據,例如使用 docker inspect -f {{.IPAddress}} 來獲取容器的 IP 地址。不過很多用戶容易被該特性的語法搞暈,並很少有人能將它的優勢發揮出來(大部分人都是通過 grep 來獲取指定數據,雖然有效但比較零散混亂)。本文將詳細介紹 -f 參數,並給出一些例子來說明如何使用它。
docker inspect
簡單地說,-f 的實參是個 Go 模版,並在容器/鏡像的元數據上以該 Go 模版作為輸入,最終返回模版指定的數據。第一個問題就是該命令說明文檔中的用詞“Go 模版”對於沒有 Go 開發經驗的人來說很模糊——我的第一感覺就是它類似恐怖的 C++ 模版。還好 Go 模版和 C++ 模版/泛型毫不相干,Go 模版是一種模板引擎,讓數據以指定的模式輸出。這個概念對於 Web 開發者是非常熟悉的,Web 領域有很多模版引擎,比如 Jinga2(用於 Python 和 Flask)、Mustache、JSP 等等,看下面的簡單示例:
$ docker inspect -f 'Hello from container {{.Name}}' jenkins Hello from container /jenkins
我們可以看到,-f 指定了一個簡單的模式(或稱之為模版)並應用於容器的元數據。當然,對於元數據,我們也可以什么都不指定:
$ docker inspect -f "This is a bit pointless" jenkins This is a bit pointless
下面讓我們來進一步看看 Go 模版的奇妙之處,例如我們可以通過模版來查找所有退出碼為非 0 的容器名:
$ docker inspect -f '{{if ne 0.0 .State.ExitCode }}{{.Name}} {{.State.ExitCode}}{{ end }}' $(docker ps -aq) /tender_colden 1 /clever_mcclintock 126 /grave_bartik 1
(無論是否匹配到,對於每個容器都會輸出一行)
或者在 jenkins-data 容器中查找卷 /var/jenkins_home 對應在 host 的目錄:
docker inspect -f '{{index .Volumes "/var/jenkins_home"}}' jenkins-data /var/lib/docker/vfs/dir/5a6f7b306b96af38723fc4d31def1cc515a0d75c785f3462482f60b730533b1a
上面的例子可能稍微有點難理解,不過沒關系,我們先來了解一下 Go 模版的基本用法。
模版指令
{{ }} 語法用於處理模版指令,大括號外的任何字符都將直接輸出。
上下文
“.” 表示“當前上下文”。大多數情況下表示了容器元數據的整個數據結構,但在某些情況下可以重新規定上下文,比如使用 with 函數:
$ docker inspect -f '{{.State.Pid}}' jenkins 6331 $ docker inspect -f '{{with .State}} {{.Pid}} {{end}}' jenkins 6331
可以使用 $ 來獲取根上下文,例如:
$ docker inspect -f '{{with .State}} {{$.Name}} has pid {{.Pid}} {{end}}' jenkins /jenkins has pid 6331
注意,單獨使用 “.” 本身也是可以的,將輸出未格式化的完整元數據:
$ docker inspect -f '{{.}}' jenkins ...
數據類型
inspect 數據可以由浮點數、字符串和布爾組成,可以使用 Go 模版內置函數進行比較判斷。雖然 Go 模版支持整數,但目前 inspect 數據中的數值類型都是浮點數,而整數應該對於大多數場景更方便(詳見該Issue)。使用字符串時可以使用雙引號。
數據中不存在的值是不可以用來比較的:
$ docker inspect -f '{{.ExecIDs}}' jenkins <no value> $ docker inspect -f '{{eq .ExecIDs .ExecIDs}}' jenkins FATA[0000] template: :1:2: executing "" at <eq .ExecIDs .ExecIDs>: error calling eq: invalid type for comparison
數據結構
inspect 數據使用 map 以及數組保存。Map 結構非常簡單,前面我們曾經展示過,可以通過 . 的鏈式來訪問 map 內部數據:
$ docker inspect -f '{{.State.ExitCode}}' jenkins 0
不過有些情況(比如 map 的鍵不是字符串)是不能直接使用 . 方式來獲取 map 值的,此時我們可以使用index 函數,前面卷的例子可以這樣寫:
docker inspect -f '{{index .Volumes "/var/jenkins_home"}}' jenkins-data /var/lib/docker/vfs/dir/5a6f7b306b96af38723fc4d31def1cc515a0d75c785f3462482f60b730533b1a
我們也可以使用 index 來獲取指定下標的數組值:
$ docker inspect -f '{{.HostConfig.Binds}}' jenkins [/var/run/docker.sock:/var/run/docker.sock /usr/bin/docker:/usr/bin/docker] $ docker inspect -f '{{index .HostConfig.Binds 1}}' jenkins /usr/bin/docker:/usr/bin/docker
函數
除了 index 函數,其他很多函數也很常用。比如邏輯函數 and、or 可以返回布爾結果。注意,函數是不能放在中間:
$ docker inspect -f '{{and true true}}' jenkins true
而不是:
$ docker inspect -f '{{true and true}}' jenkins FATA[0000] template: :1:2: executing "" at <true>: can't give argument to non-function true
下面是一些常用的比較函數:
- eq (等於)
- ne (不等於)
- lt (小於)
- le (小於等於)
- gt (大於)
- ge (大於等於)
我們可以用這些函數來比較字符串、浮點數或整數:
$ docker inspect -f '{{eq "abc" "abc"}}' jenkins true $ docker inspect -f '{{ge 1 -1}}' jenkins true $ docker inspect -f '{{lt 4.5 4.6}}' jenkins true $ docker inspect -f '{{ne 4.5 4.5}}' jenkins false
要注意的是操作數類型必須匹配,數字比較時使用浮點數:
$ docker inspect -f '{{eq "4.5" 4.5}}' jenkins FATA[0000] template: :1:2: executing "" at <eq "4.5" 4.5>: error calling eq: incompatible types for comparison $ docker inspect -f '{{gt .State.Pid 1}}' jenkins FATA[0000] template: :1:2: executing "" at <gt .State.Pid 1>: error calling gt: incompatible types for comparison $ docker inspect -f '{{gt .State.Pid 1.0}}' jenkins true
另外,可以使用 json 函數來生成 JSON 輸出:
$ docker inspect -f '{{json .NetworkSettings.Ports}}' jenkins {"50000/tcp":null,"8080/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"}]}
我們也可以使用 jq 工具來組合結果:
$ docker inspect -f '{{json .State}}' jenkins-data | jq '.StartedAt' "2015-03-15T20:26:30.526796706Z"
當然,docker inspect 的默認輸出結果就是 JSON,所以下面這樣也可以:
$ docker inspect jenkins-data | jq '.[] | .State.StartedAt' "2015-03-15T20:26:30.526796706Z"
更多函數請參考 Go 官方文檔,不過很奇怪的是官方文檔中並沒有描述 json 函數(我是從 Nathan LeClaire’s blog 中學到的),你如果知道其中原因,記得告訴我!
If 語句
條件語句 if 可以和前面的比較函數一起使用:
$ docker inspect -f '{{if eq .State.ExitCode 0.0}} Normal Exit {{else if eq .State.ExitCode 1.0}} Not a Normal Exit {{else}} Still Not a Normal Exit {{end}}' jenkins Normal Exit
注意,{{end}} 語句必須有,else if 和 else 按需使用。
