Docker格式化輸出命令:"docker inspect --format" 學習筆記

  

Docker --format 參數提供了基於 Go模板 的日誌格式化輸出輔助功能,並提供了一些內置的加強函數。php

什麼是模板?
上圖是你們熟悉的 MVC 框架(Model View Controller): Model(模型,一般在服務端)用於處理數據View(視圖,客戶端代碼)用於展示結果Controller(控制器)用於控制數據流確保 M 和 V 的同步,即一旦 M 改變,V 也應該同步更新。
而對於 View 端的處理,在不少動態語言中是經過在靜態 HTML 代碼中插入動態數據來實現的。例如 JSP 的 <%=....=%> 和 PHP 的 <?php.....?> 語法。
因爲最終展現給用戶的信息大部分是靜態不變的,只有少部分數據會根據用戶的不一樣而動態生成。好比,對於 docker ls 的輸出信息會根據附加參數的不一樣而不一樣,但其表頭信息是固定的。因此,將靜態信息固化爲模板能夠複用代碼,提升展現效率。node

Go語言提供了簡單靈活的模板支持,而基於 Go 開發的 Docker 繼承了該強大能力,使其能夠脫離 Shell 的相關操做,直接對結果進行格式化輸出。全部支持 --format 擴展的 Docker CLI 指令均支持該操做。nginx

Go模板經常使用語法
註釋
格式: {{/*註釋內容*/}}
示例:web

docker network inspect --format='{{/*查看容器的默認網關*/}}{{range .IPAM.Config}}{{.Gateway}}{{end}}' $INSTANCE_ID

變量
系統變量 {{.}}
點號表示當前對象及上下文,和 Java、C++ 中的 this 相似。能夠直接經過{{.}}獲取當前對象。
另外,若是返回結果也是一個 Struct 對象(Json 中以花括號/大括號包含),則能夠直接經過點號級聯調用,獲取子對象的指定屬性值。docker

示例代碼:shell

#能夠經過級聯調用直接讀取子對象 State 的 Status 屬性,以獲取容器的狀態信息:
docker inspect --format '{{/*讀取容器狀態*/}}{{.State.Status}}' $INSTANCE_ID    

注意: 若是須要獲取的屬性名稱包含點號(好比下列示例數據)或者以數字開頭,則不能直接經過級聯調用獲取信息。由於屬性名稱中的點號會被解析成級聯信息,進而致使返回錯誤結果。即使使用引號將其包含也會提示語法格式錯誤。此時,須要經過 index 來讀取指定屬性信息。json

"Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        }, 

示例操做:數組

# 直接級聯調用會提示找不到數據:
docker inspect --format '{{.Options.com.docker.network.driver.mtu}}' bridge
<no value>

# 用引號括起來會提示語法錯誤:
docker inspect --format '{{.Options."com.docker.network.driver.mtu"}}' bridge
Template parsing error: template: :1: bad character U+0022 '"'

# 正確的用法,必須用 index 讀取指定屬性名稱的屬性值:
docker inspect --format '{{/*讀取網絡在hosts上的名稱*/}}{{index .Options "com.docker.network.bridge.name"}}' bridge
docker0

自定義變量
能夠在處理過程當中設置自定義變量,而後結合自定義變量作更復雜的處理。 若是自定義變量的返回值是對象,則能夠經過點號進一步級聯訪問其屬性。好比 {{$Myvar.Field1}}。bash

示例操做:markdown

# 結合變量的使用,對輸出結果進行組裝展示,以輸出容器的全部綁定端口列表:
docker inspect --format '{{/*經過變量組合展現容器綁定端口列表*/}}已綁定端口列表:{{println}}{{range $p,$conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{println}}{{end}}' Web_web_1

# 示例輸出信息
已綁定端口列表:
80/tcp -> 32770
8081/tcp -> 8081

遍歷(循環):range
格式:

{{range pipeline}}{{.}}{{end}}
{{range pipeline}}{{.}}{{else}}{{.}}{{end}}

range 用於遍歷結構內返回值的全部數據。支持的類型包括 array, slice, map 和 channel。使用要點:
-  對應的值長度爲 0 時,range 不會執行。
-  結構內部如要使用外部的變量,須要在前面加 引用,好比Var2。
-  range 也支持 else 操做。效果是:當返回值爲空或長度爲 0 時執行 else 內的內容。

示例操做:

# 查看容器網絡下已掛載的全部容器名稱,若是沒有掛載任何容器,則輸出 "With No Containers"
docker inspect --format '{{range .Containers}}{{.Name}}{{println}}{{else}}With No Containers{{end}}' bridge
brtest
peaceful_brown
test

docker inspect --format '{{range .Containers}}{{.Name}}{{println}}{{else}}With No Containers{{end}}' none
With No Containers

索引: index
若是返回結果是一個 map, slice, array 或 string,則可使用 index 加索引序號(從零開始計數)來讀取屬性值。

示例代碼:

# docker inspect $INSTANCE_ID 查看容器綁定的端口信息,其 Config 屬性就是一個 Map,包含了全部子網信息。
...
 "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.31.254.1/24",
                    "Gateway": "172.31.254.1"
                }
            ]
        },            
...

示例操做:

# 經過索引序號讀取默認網關
docker inspect bridge --format '{{/*查看網絡的默認網關*/}}{{(index .IPAM.Config 0).Gateway}}'

判斷:if … else … end
基本判斷
1)  not
   返回單一參數的布爾否認值,即返回輸入參數的否認值。

示例:

# 若是容器的 restarting 設置爲 false,則返回信息「容器沒有配置重啓策略」
docker inspect --format '{{if not .State.Restarting}}容器沒有配置重啓策略{{end}}' $(docker ps -q)

2) or
-   {{or x y}}: 表示若是 x 爲真返回 x,不然返回 y。
-   {{or x y z}}:後面跟多個參數時會逐一判斷每一個參數,並返回第一個非空的參數。若是都爲 false,則返回最後一個參數。
-  除了 null(空)和 false 被識別爲 false,其它值(字符串、數字、對象等)均被識別爲 true。

示例:

docker inspect --format '{{or .State.Status .State.Restarting}}' $INSTANCE_ID

判斷條件
判斷語句一般須要結合判斷條件一塊兒使用,使用格式基本相同:

{{if 判斷條件 .Var1 .Var2}}{{end}}

go模板支持以下判斷方式:
1)  eq: 相等,即 arg1 == arg2。比較特殊的是,它支持多個參數進行與比較,此時,它會將第一個參數和其他參數依次比較,返回下式的結果:

{{if eq true .Var1 .Var2 .Var3}}{{end}}
# 效果等同於:
arg1==arg2 || arg1==arg3 || arg1==arg4 ...

2) ne: 不等,即 arg1 != arg2。
3) lt: 小於,即 arg1 < arg2。
4) le: 小於等於,即 arg1 <= arg2。
5) gt: 大於,即 arg1 > arg2。
6) ge: 大於等於,即 arg1 >= arg2。

判斷的使用
格式:

{{if pipeline}}{{end}}
{{if pipeline}}{{else}}{{if pipeline}}{{end}}{{end}}
{{if pipeline}}{{else if pipeline}}{{else}}{{end}}

示例:

# 輸出全部已中止的容器名稱:
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{end}}' $(docker ps -aq)
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else}}該容器還在運行{{end}}' $(docker ps -aq)
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else if .}}該容器還在運行{{end}}' $(docker ps -aq)

# 輸出全部已中止或配置了 Restarting 策略的容器名稱
docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else if eq .State.Restarting true}}容器{{.Name}}配置了Restarting策略.{{else}}{{end}}' $(docker ps -aq)

打印信息
docker --format 默認調用 go語言的 print 函數對模板中的字符串進行輸出。而 go語言還有另外 2 種類似的內置函數,對比說明以下:
print:  將傳入的對象轉換爲字符串並寫入到標準輸出中。若是後跟多個參數,輸出結果之間會自動填充空格進行分隔。
println:  功能和 print 相似,但會在結尾添加一個換行符。也能夠直接使用 {{println}} 來換行。
printf:   與 shell 等環境一致,可配合佔位符用於格式化輸出。

對比示例輸出:

docker inspect --format '{{.State.Pid}}{{.State.ExitCode}}' $INSTANCE_ID 
240390

docker inspect --format '{{print .State.Pid .State.ExitCode}}' $INSTANCE_ID
24039 0

docker inspect --format '{{.State.Pid}}{{println " 從這換行"}}{{.State.ExitCode}}' $INSTANCE_ID 
24039 從這換行
0

docker inspect --format '{{printf "Pid:%d ExitCode:%d" .State.Pid .State.ExitCode}}' $INSTANCE_ID
Pid:24039 ExitCode:0

管道
管道 即 pipeline ,與 shell 中相似,能夠是上下文的變量輸出,也能夠是函數經過管道傳遞的返回值。
示例:

{{.Con | markdown | addlinks}}
{{.Name | printf "%s"}}

內置函數 len
內置函數 len 返回相應對象的長度。
示例:

docker inspect --format '{{len .Name}}' $INSTANCE_ID

Docker 加強模板及函數
Docker 基於 go模板的基礎上,構建了一些內置函數。

json
Docker 默認以字符串顯示返回結果。而該函數能夠將結果格式化爲壓縮後的 json 格式數據。
示例:

# 獲取 Config 字段對應的 json 數據
docker inspect --format='{{json .Config}}' $INSTANCE_ID

join
用指定的字符串將返回結果鏈接後一塊兒展現。操做對象必須是字符串數組。
示例:

# 輸出容器配置的全部 Entrypoint 參數,以 " , " 分隔:
docker inspect --format '{{join .Config.Entrypoint " , "}}' $INSTANCE_ID

lower
將返回結果中的字母所有轉換爲小寫。操做對象必須是字符串。

docker inspect --format "{{lower .Name}}" $INSTANCE_ID

upper
將返回結果中的字母所有轉換爲大寫。操做對象必須是字符串。

docker inspect --format "{{upper .Name}}" $INSTANCE_ID

title
將返回結果的首字母轉換爲大寫。操做對象必須是字符串,並且不能是純數字。

docker inspect --format "{{title .State.Status}}" $INSTANCE_ID

split
使用指定分隔符將返回結果拆分爲字符串列表。操做對象必須是字符串且不能是純數字。同時,字符串中必須包含相應的分隔符,不然會直接忽略操做。

docker inspect --format '{{split .HostsPath "/"}}' $INSTANCE_ID

============================經常使用docker inspect --format 輸出示例========================

[root@node1 ~]# docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS               NAMES
2ed603e52896        172.16.60.214:5000/kevin_nginx   "/bin/sh -c '/usr/..."   13 minutes ago      Up 13 minutes                           docker-test111
24e6607534f1        172.16.60.214:5000/kevin_nginx   "/bin/sh -c '/usr/..."   13 minutes ago      Up 13 minutes                           docker-test11
19be6b264b6e        172.16.60.214:5000/kevin_nginx   "/bin/sh -c '/usr/..."   13 minutes ago      Up 13 minutes                           docker-test1
 
1) 獲取容器的IP (後面使用容器名或容器ID均可以)
[root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
192.10.160.193
173.20.19.128
17.16.10.128
 
[root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-test1
17.16.10.128
 
2) 獲取容器的MAC地址
[root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' $(docker ps -a -q)
ee:ee:ee:ee:ee:ee
ee:ee:ee:ee:ee:ee
ee:ee:ee:ee:ee:ee
 
[root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' docker-test1
ee:ee:ee:ee:ee:ee
 
3) 獲取容器Name
[root@node1 ~]# docker inspect --format='{{.Name}}' $(docker ps -aq)
/docker-test111
/docker-test11
/docker-test1
/calico-node
 
[root@node1 ~]# docker inspect --format='{{.Name}}' $(docker ps -aq)|cut -d"/" -f2
docker-test111
docker-test11
docker-test1
 
[root@node1 ~]# docker inspect --format='{{.Name}}' docker-test1
/docker-test1
 
[root@node1 ~]# docker inspect --format='{{.Name}}' docker-test1|cut -d"/" -f2
docker-test1
 
4) 獲取容器Hostname
[root@node1 ~]# docker inspect --format '{{ .Config.Hostname }}' $(docker ps -q)
2ed603e52896
24e6607534f1
19be6b264b6e
 
[root@node1 ~]# docker inspect --format '{{ .Config.Hostname }}' docker-test1
19be6b264b6e
 
5) Hostname Name IP
[root@node1 ~]# docker inspect --format 'Hostname:{{ .Config.Hostname }}  Name:{{.Name}} IP:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
Hostname:2ed603e52896  Name:/docker-test111 IP:192.10.160.193
Hostname:24e6607534f1  Name:/docker-test11 IP:173.20.19.128
Hostname:19be6b264b6e  Name:/docker-test1 IP:17.16.10.128
 
[root@node1 ~]# docker inspect --format 'Hostname:{{ .Config.Hostname }}  Name:{{.Name}} IP:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-test1
Hostname:19be6b264b6e  Name:/docker-test1 IP:17.16.10.128
 
6) 獲取容器的log path
[root@node1 ~]# docker inspect --format='{{.LogPath}}' `docker ps -a -q`
[root@node1 ~]# docker inspect --format='{{.LogPath}}' docker-test1
 
7) 獲取容器的image鏡像名稱
[root@node1 ~]# docker inspect --format='{{.Config.Image}}' `docker ps -a -q`
172.16.60.214:5000/kevin_nginx
172.16.60.214:5000/kevin_nginx
172.16.60.214:5000/kevin_nginx
quay.io/calico/node:v2.6.10
[root@node1 ~]# docker inspect --format='{{.Config.Image}}' docker-test1
172.16.60.214:5000/kevin_nginx
 
8) 獲取容器綁定的端口(port bindings)
[root@node1 ~]# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' `docker ps -a -q`
[root@node1 ~]# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' docker-test1

9) 獲取service實例的Ip
[root@swarm-manager-node ~]# docker service ps my-test  
ID                    NAME       IMAGE                                                   NODE                         DESIRED   STATE  CURRENT STATE    ERROR  PORTS
t71gqufekv2o  my-test.1  172.16.60.214:5000/kevin_nginx:latest  swarm-node2              Running    Running 16 seconds ago         
9cuq2yf10d60 my-test.2  172.16.60.214:5000/kevin_nginx:latest  swarm-manager-node  Running   Running 16 seconds ago         
srt2yo817kpv  my-test.3  172.16.60.214:5000/kevin_nginx:latest  swarm-node1               Running    Running 16 seconds ago   

[root@swarm-manager-node ~]# docker inspect ` docker service ps my-test -q` --format '{{range .NetworksAttachments}}{{.Addresses}}{{end}}' | cut -d '[' -f2|cut -d ']' -f1
10.255.0.7/16
10.255.0.8/16
10.255.0.9/16

10) 獲取service示例的container ID  (獲取的是ID的全稱,通常只要取ID前面12個字符就能夠了)
[root@swarm-manager-node ~]# docker inspect ` docker service ps my-test -q` --format '{{ .Status.ContainerStatus.ContainerID }}'
c6c18a74a465163757fe928fec9e633223200f92d1c59e5d2d77eabfaa5ae93a
5f558bb014ea3d3eef5c8d4bd70e2e3048d7fc6725538303be960ac658d93b32
dde578bf60190a63ed5c8c4a9f5a3044566a159e8debe8717342e263c6199f26
相關文章
相關標籤/搜索