Docker --format 参数提供了基于 Go模板 的日志格式化输出辅助功能,并提供了一些内置的增强函数。

什么是模板?
上图是大家熟悉的 MVC 框架(Model View Controller): Model(模型,通常在服务端)用于处理数据、View(视图,客户端代码)用于展现结果、Controller(控制器)用于控制数据流,确保 M 和 V 的同步,即一旦 M 改变,V 也应该同步更新。
而对于 View 端的处理,在很多动态语言中是通过在静态 HTML 代码中插入动态数据来实现的。例如 JSP 的 <%=....=%> 和 PHP 的 <?php.....?> 语法。
由于最终展示给用户的信息大部分是静态不变的,只有少部分数据会根据用户的不同而动态生成。比如,对于 docker ls 的输出信息会根据附加参数的不同而不同,但其表头信息是固定的。所以,将静态信息固化为模板可以复用代码,提高展示效率。

Go语言提供了简单灵活的模板支持,而基于 Go 开发的 Docker 继承了该强大能力,使其可以脱离 Shell 的相关操作,直接对结果进行格式化输出。所有支持 --format 扩展的 Docker CLI 指令均支持该操作。

Go模板常用语法
注释
格式: {{/*注释内容*/}}
示例:

  1. docker network inspect --format='{{/*查看容器的默认网关*/}}{{range .IPAM.Config}}{{.Gateway}}{{end}}' $INSTANCE_ID

变量
系统变量 {{.}}
点号表示当前对象及上下文,和 Java、C++ 中的 this 类似。可以直接通过{{.}}获取当前对象。
另外,如果返回结果也是一个 Struct 对象(Json 中以花括号/大括号包含),则可以直接通过点号级联调用,获取子对象的指定属性值。

示例代码:

  1. #可以通过级联调用直接读取子对象 State 的 Status 属性,以获取容器的状态信息:
  2. docker inspect --format '{{/*读取容器状态*/}}{{.State.Status}}' $INSTANCE_ID

注意: 如果需要获取的属性名称包含点号(比如下列示例数据)或者以数字开头,则不能直接通过级联调用获取信息。因为属性名称中的点号会被解析成级联信息,进而导致返回错误结果。即便使用引号将其包含也会提示语法格式错误。此时,需要通过 index 来读取指定属性信息。

  1. "Options": {
  2. "com.docker.network.bridge.default_bridge": "true",
  3. "com.docker.network.bridge.enable_icc": "true",
  4. "com.docker.network.bridge.enable_ip_masquerade": "true",
  5. "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
  6. "com.docker.network.bridge.name": "docker0",
  7. "com.docker.network.driver.mtu": "1500"
  8. },

示例操作:

  1. # 直接级联调用会提示找不到数据:
  2. docker inspect --format '{{.Options.com.docker.network.driver.mtu}}' bridge
  3. <no value>
  4.  
  5. # 用引号括起来会提示语法错误:
  6. docker inspect --format '{{.Options."com.docker.network.driver.mtu"}}' bridge
  7. Template parsing error: template: :1: bad character U+0022 '"'
  8.  
  9. # 正确的用法,必须用 index 读取指定属性名称的属性值:
  10. docker inspect --format '{{/*读取网络在hosts上的名称*/}}{{index .Options "com.docker.network.bridge.name"}}' bridge
  11. docker0

自定义变量
可以在处理过程中设置自定义变量,然后结合自定义变量做更复杂的处理。 如果自定义变量的返回值是对象,则可以通过点号进一步级联访问其属性。比如 {{$Myvar.Field1}}。

示例操作:

  1. # 结合变量的使用,对输出结果进行组装展现,以输出容器的所有绑定端口列表:
  2. docker inspect --format '{{/*通过变量组合展示容器绑定端口列表*/}}已绑定端口列表:{{println}}{{range $p,$conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{println}}{{end}}' Web_web_1
  3.  
  4. # 示例输出信息
  5. 已绑定端口列表:
  6. 80/tcp -> 32770
  7. 8081/tcp -> 8081

遍历(循环):range
格式:

  1. {{range pipeline}}{{.}}{{end}}
  2. {{range pipeline}}{{.}}{{else}}{{.}}{{end}}

range 用于遍历结构内返回值的所有数据。支持的类型包括 array, slice, map 和 channel。使用要点:
-  对应的值长度为 0 时,range 不会执行。
-  结构内部如要使用外部的变量,需要在前面加 引用,比如Var2。
-  range 也支持 else 操作。效果是:当返回值为空或长度为 0 时执行 else 内的内容。

示例操作:

  1. # 查看容器网络下已挂载的所有容器名称,如果没有挂载任何容器,则输出 "With No Containers"
  2. docker inspect --format '{{range .Containers}}{{.Name}}{{println}}{{else}}With No Containers{{end}}' bridge
  3. brtest
  4. peaceful_brown
  5. test
  6.  
  7. docker inspect --format '{{range .Containers}}{{.Name}}{{println}}{{else}}With No Containers{{end}}' none
  8. With No Containers

索引: index
如果返回结果是一个 map, slice, array 或 string,则可以使用 index 加索引序号(从零开始计数)来读取属性值。

示例代码:

  1. # docker inspect $INSTANCE_ID 查看容器绑定的端口信息,其 Config 属性就是一个 Map,包含了所有子网信息。
  2. ...
  3. "IPAM": {
  4. "Driver": "default",
  5. "Options": null,
  6. "Config": [
  7. {
  8. "Subnet": "172.31.254.1/24",
  9. "Gateway": "172.31.254.1"
  10. }
  11. ]
  12. },
  13. ...

示例操作:

  1. # 通过索引序号读取默认网关
  2. docker inspect bridge --format '{{/*查看网络的默认网关*/}}{{(index .IPAM.Config 0).Gateway}}'

判断:if … else … end
基本判断
1)  not
   返回单一参数的布尔否定值,即返回输入参数的否定值。

示例:

  1. # 如果容器的 restarting 设置为 false,则返回信息“容器没有配置重启策略”
  2. 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。

示例:

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

判断条件
判断语句通常需要结合判断条件一起使用,使用格式基本相同:

  1. {{if 判断条件 .Var1 .Var2}}{{end}}

go模板支持如下判断方式:
1)  eq: 相等,即 arg1 == arg2。比较特殊的是,它支持多个参数进行与比较,此时,它会将第一个参数和其余参数依次比较,返回下式的结果:

  1. {{if eq true .Var1 .Var2 .Var3}}{{end}}
  2. # 效果等同于:
  3. 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。

判断的使用
格式:

  1. {{if pipeline}}{{end}}
  2. {{if pipeline}}{{else}}{{if pipeline}}{{end}}{{end}}
  3. {{if pipeline}}{{else if pipeline}}{{else}}{{end}}

示例:

  1. # 输出所有已停止的容器名称:
  2. docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{end}}' $(docker ps -aq)
  3. docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else}}该容器还在运行{{end}}' $(docker ps -aq)
  4. docker inspect --format '{{if ne 0.0 .State.ExitCode}}{{.Name}}{{else if .}}该容器还在运行{{end}}' $(docker ps -aq)
  5.  
  6. # 输出所有已停止或配置了 Restarting 策略的容器名称
  7. 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 等环境一致,可配合占位符用于格式化输出。

对比示例输出:

  1. docker inspect --format '{{.State.Pid}}{{.State.ExitCode}}' $INSTANCE_ID
  2. 240390
  3.  
  4. docker inspect --format '{{print .State.Pid .State.ExitCode}}' $INSTANCE_ID
  5. 24039 0
  6.  
  7. docker inspect --format '{{.State.Pid}}{{println " 从这换行"}}{{.State.ExitCode}}' $INSTANCE_ID
  8. 24039 从这换行
  9. 0
  10.  
  11. docker inspect --format '{{printf "Pid:%d ExitCode:%d" .State.Pid .State.ExitCode}}' $INSTANCE_ID
  12. Pid:24039 ExitCode:0

管道
管道 即 pipeline ,与 shell 中类似,可以是上下文的变量输出,也可以是函数通过管道传递的返回值。
示例:

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

内置函数 len
内置函数 len 返回相应对象的长度。
示例:

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

Docker 增强模板及函数
Docker 基于 go模板的基础上,构建了一些内置函数。

json
Docker 默认以字符串显示返回结果。而该函数可以将结果格式化为压缩后的 json 格式数据。
示例:

  1. # 获取 Config 字段对应的 json 数据
  2. docker inspect --format='{{json .Config}}' $INSTANCE_ID

join
用指定的字符串将返回结果连接后一起展示。操作对象必须是字符串数组。
示例:

  1. # 输出容器配置的所有 Entrypoint 参数,以 " , " 分隔:
  2. docker inspect --format '{{join .Config.Entrypoint " , "}}' $INSTANCE_ID

lower
将返回结果中的字母全部转换为小写。操作对象必须是字符串。

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

upper
将返回结果中的字母全部转换为大写。操作对象必须是字符串。

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

title
将返回结果的首字母转换为大写。操作对象必须是字符串,而且不能是纯数字。

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

split
使用指定分隔符将返回结果拆分为字符串列表。操作对象必须是字符串且不能是纯数字。同时,字符串中必须包含相应的分隔符,否则会直接忽略操作。

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

============================常用docker inspect --format 输出示例========================

  1. [root@node1 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 2ed603e52896 172.16.60.214:5000/kevin_nginx "/bin/sh -c '/usr/..." 13 minutes ago Up 13 minutes docker-test111
  4. 24e6607534f1 172.16.60.214:5000/kevin_nginx "/bin/sh -c '/usr/..." 13 minutes ago Up 13 minutes docker-test11
  5. 19be6b264b6e 172.16.60.214:5000/kevin_nginx "/bin/sh -c '/usr/..." 13 minutes ago Up 13 minutes docker-test1
  6.  
  7. 1) 获取容器的IP (后面使用容器名或容器ID都可以)
  8. [root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
  9. 192.10.160.193
  10. 173.20.19.128
  11. 17.16.10.128
  12.  
  13. [root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-test1
  14. 17.16.10.128
  15.  
  16. 2) 获取容器的MAC地址
  17. [root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' $(docker ps -a -q)
  18. ee:ee:ee:ee:ee:ee
  19. ee:ee:ee:ee:ee:ee
  20. ee:ee:ee:ee:ee:ee
  21.  
  22. [root@node1 ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' docker-test1
  23. ee:ee:ee:ee:ee:ee
  24.  
  25. 3) 获取容器Name
  26. [root@node1 ~]# docker inspect --format='{{.Name}}' $(docker ps -aq)
  27. /docker-test111
  28. /docker-test11
  29. /docker-test1
  30. /calico-node
  31.  
  32. [root@node1 ~]# docker inspect --format='{{.Name}}' $(docker ps -aq)|cut -d"/" -f2
  33. docker-test111
  34. docker-test11
  35. docker-test1
  36.  
  37. [root@node1 ~]# docker inspect --format='{{.Name}}' docker-test1
  38. /docker-test1
  39.  
  40. [root@node1 ~]# docker inspect --format='{{.Name}}' docker-test1|cut -d"/" -f2
  41. docker-test1
  42.  
  43. 4) 获取容器Hostname
  44. [root@node1 ~]# docker inspect --format '{{ .Config.Hostname }}' $(docker ps -q)
  45. 2ed603e52896
  46. 24e6607534f1
  47. 19be6b264b6e
  48.  
  49. [root@node1 ~]# docker inspect --format '{{ .Config.Hostname }}' docker-test1
  50. 19be6b264b6e
  51.  
  52. 5) Hostname Name IP
  53. [root@node1 ~]# docker inspect --format 'Hostname:{{ .Config.Hostname }} Name:{{.Name}} IP:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
  54. Hostname:2ed603e52896 Name:/docker-test111 IP:192.10.160.193
  55. Hostname:24e6607534f1 Name:/docker-test11 IP:173.20.19.128
  56. Hostname:19be6b264b6e Name:/docker-test1 IP:17.16.10.128
  57.  
  58. [root@node1 ~]# docker inspect --format 'Hostname:{{ .Config.Hostname }} Name:{{.Name}} IP:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-test1
  59. Hostname:19be6b264b6e Name:/docker-test1 IP:17.16.10.128
  60.  
  61. 6) 获取容器的log path
  62. [root@node1 ~]# docker inspect --format='{{.LogPath}}' `docker ps -a -q`
  63. [root@node1 ~]# docker inspect --format='{{.LogPath}}' docker-test1
  64.  
  65. 7) 获取容器的image镜像名称
  66. [root@node1 ~]# docker inspect --format='{{.Config.Image}}' `docker ps -a -q`
  67. 172.16.60.214:5000/kevin_nginx
  68. 172.16.60.214:5000/kevin_nginx
  69. 172.16.60.214:5000/kevin_nginx
  70. quay.io/calico/node:v2.6.10
  71. [root@node1 ~]# docker inspect --format='{{.Config.Image}}' docker-test1
  72. 172.16.60.214:5000/kevin_nginx
  73.  
  74. 8) 获取容器绑定的端口(port bindings)
  75. [root@node1 ~]# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' `docker ps -a -q`
  76. [root@node1 ~]# docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' docker-test1
  77.  
  78. 9) 获取service实例的Ip
  79. [root@swarm-manager-node ~]# docker service ps my-test
  80. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  81. t71gqufekv2o my-test.1 172.16.60.214:5000/kevin_nginx:latest swarm-node2 Running Running 16 seconds ago
  82. 9cuq2yf10d60 my-test.2 172.16.60.214:5000/kevin_nginx:latest swarm-manager-node Running Running 16 seconds ago
  83. srt2yo817kpv my-test.3 172.16.60.214:5000/kevin_nginx:latest swarm-node1 Running Running 16 seconds ago
  84.  
  85. [root@swarm-manager-node ~]# docker inspect ` docker service ps my-test -q` --format '{{range .NetworksAttachments}}{{.Addresses}}{{end}}' | cut -d '[' -f2|cut -d ']' -f1
  86. 10.255.0.7/16
  87. 10.255.0.8/16
  88. 10.255.0.9/16
  89.  
  90. 10) 获取service示例的container ID (获取的是ID的全称,一般只要取ID前面12个字符就可以了)
  91. [root@swarm-manager-node ~]# docker inspect ` docker service ps my-test -q` --format '{{ .Status.ContainerStatus.ContainerID }}'
  92. c6c18a74a465163757fe928fec9e633223200f92d1c59e5d2d77eabfaa5ae93a
  93. 5f558bb014ea3d3eef5c8d4bd70e2e3048d7fc6725538303be960ac658d93b32
  94. dde578bf60190a63ed5c8c4a9f5a3044566a159e8debe8717342e263c6199f26

Docker inspect - format格式化输出 - 运维笔记的更多相关文章

  1. 运维笔记--给正在运行的Docker容器动态绑定卷组(挂载指定目录)

    场景描述: 操作系统: ubuntu16.04, docker版本: Docker version 19.03.1 系统运行一段时间后,该服务器上有一个运行中docker容器,需要在容器里边挂载本地服 ...

  2. Java String 函数常用操作 & format() 格式化输出,代码详解

    package _String_; import java.util.*; import java.math.*; import java.lang.*; public class _Strings ...

  3. Linux系统运维笔记(五),CentOS 6.4安装java程序

    Linux系统运维笔记(五),CentOS 6.4安装java程序 用eclipse编译通的java程序,现需要实施到服务器.实施步骤: 一,导出程序成jar包. 1,在主类编辑界面点右健,选  ru ...

  4. Linux系统运维笔记(四),CentOS 6.4安装 MongoDB

    Linux系统运维笔记(四),CentOS 6.4安装 MongoDB 1,下载 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6 ...

  5. Linux系统运维笔记(四),CentOS 6.4安装Nginx

    Linux系统运维笔记(四),CentOS 6.4安装Nginx 1,安装编译工具及库文件 yum -y install make zlib zlib-devel gcc-c++ libtool op ...

  6. Linux系统运维笔记(三),设置IP和DNS

    Linux系统运维笔记(三),设置IP和DNS 手工配置静态的IP地址 也就是手工配置IP地址.子网掩码.网关和DNS. vi /etc/sysconfig/network-scripts/ifcfg ...

  7. Linux系统运维笔记(二),Linux文件编辑命令

    Linux系统运维笔记 Linux文件编辑命令 首先我们使用命令 vi filename 打开一个文件,这个时候进入到的是命令模式 接下来我们按i,然后键盘随便输入写内容. 然后按ESC重新进入到命令 ...

  8. Linux系统运维笔记(一),查看系统版本和设置系统时间

    Linux系统运维笔记 查看系统版本和设置系统时间 查看系统版本 lsb_release -a (适用于所有的linux,包括Redhat.SuSE.Debian等发行版,但是在debian下要安装l ...

  9. Linux系统运维笔记(6),CentOS 7.6双网卡路由配置

    Linux系统运维笔记(6),CentOS 7.6双网卡路由配置. 一,先确认系统版本: [root@localhost ~]# cat /etc/redhat-releaseCentOS Linux ...

随机推荐

  1. Asp.net Mvc身份验证

    1.安装组件 Microsoft.AspNet.Identity.Core,身份认证核心组件 安装Microsoft.AspNet.Identity.EntityFramework,EF实现身份认证 ...

  2. V4L2 driver -整体架构

    我的uvc开源地址:gitee-uvc 字符设备驱动程序核心:V4L2本身就是一个字符设备,具有字符设备所有的特性,暴露接口给用户空间. V4L2 驱动核心:主要是构建一个内核中标准视频设备驱动的框架 ...

  3. 使用Tampermonkey(油猴) 插件,重新实现了,百度搜索热点过滤功能

    昨天晚上,花了点时间学习了Chrome插件的制作方法,并书写了<Chrome 百度搜索热点过滤插件 - 开源软件>这一文章,简单地介绍自己实现的百度搜索热点过滤神器的原理和使用方式,并进行 ...

  4. Python之对象的永久保存模块---pickle

    经常遇到在Python程序运行中得到了一些字符串.列表.字典等数据,想要长久的保存下来,方便以后使用,而不是简单的放入内存中关机断电就丢失数据. 这个时候Pickle模块就派上用场了,它可以将对象转换 ...

  5. MATLAB用二分法、不动点迭代法及Newton迭代(切线)法求非线性方程的根

    MATLAB用二分法.不动点迭代法及Newton迭代(切线)法求非线性方程的根 作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ 一.实验原理 二.实验步骤 ...

  6. hubilder打包+C#服务端个推服务实现

    关于推送鼓捣了好长时间,这里不再写helloworld了,只讲里面遇到的问题. 1.关于苹果开发者平台上的注册 网上很多的教程,只要按照步骤来设置就行了,在 iOS证书(.p12)和描述文件(.mob ...

  7. 使用Gitkraken进行其他Git操作

    使用Gitkraken进行其他Git操作 查看某次 commit 的文件改动 使用 Gitkraken 能非常方便的看到任意一次的 commit 对项目文件的改动. 具体操作是:在树状分支图上单击某个 ...

  8. phpize安装php扩展CURL

    进入php源码包curl扩展目录 cd php-/ext/curl phpize ./configure --with-php-config=/usr/local/webserver/php/bin/ ...

  9. SQL查询语句,怎样查询重复数据

    SQL查询语句,怎样查询重复数据 2012-02-22 14:50神奇的马骁勇 | 浏览 0 次 有表A, 中有字段id, name, memo现在有很多id重复的数据,怎么把这些重复的都查出来?gr ...

  10. dp HDU - 5074

    按题意推表达式 #include<cstdio> #include<cstring> #define max(a, b) (a)>(b)?(a):(b) ][], num ...