Docker CLI 的 --format 参数提供了基于 Go模板 的日志格式化输出辅助功能,并提供了一些内置的增强函数。 本文结合 docker 日志输出格式化的具体操作示例,先简要介绍 Go模板的常用语法,再介绍 Docker 内置增强函数的使用。
上图是大家熟悉的 MVC 框架(Model View Controller): Model(模型,通常在服务端)用于处理数据、View(视图,客户端代码)用于展现结果、Controller(控制器)用于控制数据流,确保 M 和 V 的同步,即一旦 M 改变,V 也应该同步更新。
而对于 View 端的处理,在很多动态语言中是通过在静态 HTML 代码中插入动态数据来实现的。例如 JSP 的 <code><%=....=%></code> 和 PHP 的 <code><?php.....?></code> 语法。
由于最终展示给用户的信息大部分是静态不变的,只有少部分数据会根据用户的不同而动态生成。比如,对于 docker ls 的输出信息会根据附加参数的不同而不同,但其表头信息是固定的。所以,将静态信息固化为模板可以复用代码,提高展示效率。
Go语言提供了简单灵活的模板支持,而基于 Go 开发的 Docker 继承了该强大能力,使其可以脱离 Shell 的相关操作,直接对结果进行格式化输出。所有支持 --format 扩展的 Docker CLI 指令均支持该操作。
格式: <code>{{/*注释内容*/}}</code>
示例:
点号表示当前对象及上下文,和 Java、C++ 中的 this 类似。可以直接通过<code>{{.}}</code>获取当前对象。
另外,如果返回结果也是一个 Struct 对象(Json 中以花括号/大括号包含),则可以直接通过点号级联调用,获取子对象的指定属性值。
示例代码:
注意: 如果需要获取的属性名称包含点号(比如下列示例数据)或者以数字开头,则不能直接通过级联调用获取信息。因为属性名称中的点号会被解析成级联信息,进而导致返回错误结果。即便使用引号将其包含也会提示语法格式错误。此时,需要通过 index 来读取指定属性信息。
示例操作:
可以在处理过程中设置自定义变量,然后结合自定义变量做更复杂的处理。 如果自定义变量的返回值是对象,则可以通过点号进一步级联访问其属性。比如 {{$Myvar.Field1}}。
格式:
range 用于遍历结构内返回值的所有数据。支持的类型包括 array, slice, map 和 channel。使用要点:
对应的值长度为 0 时,range 不会执行。
结构内部如要使用外部的变量,需要在前面加 $ 引用,比如 $Var2。
range 也支持 else 操作。效果是:当返回值为空或长度为 0 时执行 else 内的内容。
如果返回结果是一个 map, slice, array 或 string,则可以使用 index 加索引序号(从零开始计数)来读取属性值。
not
返回单一参数的布尔否定值,即返回输入参数的否定值。
or:
{{or x y}}: 表示如果 x 为真返回 x,否则返回 y。
{{or x y z}}:后面跟多个参数时会逐一判断每个参数,并返回第一个非空的参数。如果都为 false,则返回最后一个参数。
除了 null(空)和 false 被识别为 false,其它值(字符串、数字、对象等)均被识别为 true。
判断语句通常需要结合判断条件一起使用,使用格式基本相同:
go模板支持如下判断方式:
eq: 相等,即 arg1 == arg2。比较特殊的是,它支持多个参数进行与比较,此时,它会将第一个参数和其余参数依次比较,返回下式的结果:
ne: 不等,即 arg1 != arg2。
lt: 小于,即 arg1 < arg2。
le: 小于等于,即 arg1 <= arg2。
gt: 大于,即 arg1 > arg2。
ge: 大于等于,即 arg1 >= arg2。
docker --format 默认调用 go语言的 print 函数对模板中的字符串进行输出。而 go语言还有另外 2 种相似的内置函数,对比说明如下:
print: 将传入的对象转换为字符串并写入到标准输出中。如果后跟多个参数,输出结果之间会自动填充空格进行分隔。
println: 功能和 print 类似,但会在结尾添加一个换行符。也可以直接使用 <code>{{println}}</code> 来换行。
对比示例输出:
管道 即 pipeline ,与 shell 中类似,可以是上下文的变量输出,也可以是函数通过管道传递的返回值。
内置函数 len 返回相应对象的长度。
Docker 基于 go模板的基础上,构建了一些内置函数。下面逐一说明:
Docker 默认以字符串显示返回结果。而该函数可以将结果格式化为压缩后的 json 格式数据。
用指定的字符串将返回结果连接后一起展示。操作对象必须是字符串数组。
将返回结果中的字母全部转换为小写。操作对象必须是字符串。
将返回结果中的字母全部转换为大写。操作对象必须是字符串。
将返回结果的首字母转换为大写。操作对象必须是字符串,而且不能是纯数字。
使用指定分隔符将返回结果拆分为字符串列表。操作对象必须是字符串且不能是纯数字。同时,字符串中必须包含相应的分隔符,否则会直接忽略操作。
<a href="https://golang.org/pkg/html/template/">Go模板官方文档</a>
<a href="https://docs.docker-cn.com/engine/admin/formatting/#template-functions">Docker 官方日志格式化说明文档</a>