Docker version --format の特定の値だけを取得する。もしくは全てを JSON で取得するための Go template の書式

<h1>Docker の version 情報の値をスクリプトで取得したい</h1>

> Docker の `version` コマンドで表示される値を、`--format` オプションで Go テンプレートのフォーマットを指定して取得したい。でも **`Go template` のフォーマットがわからない**。

```shell-session
$ docker version
Client: Docker Engine - Community
 Version:           19.03.2
 API version:       1.40
 Go version:        go1.12.8
 Git commit:        6a30dfc
 Built:             Thu Aug 29 05:26:49 2019
 OS/Arch:           darwin/amd64 <--------------- たとえばこれの amd64 が欲しい
 Experimental:      false

Server: Docker Engine - Community
...（略）...
```

例えば、docker で検知しているアーキテクチャとか。つまり、上記の `Client` 項目にある `OS/Arch` の `Arch` の値のみ取得したいが **`grep` は使いたくない**、と駄々をこねたいのです。

`docker version --help` しても `-f, --format string  Format the output using the given Go template`（訳：「Go テンプレートで指定されたフォーマットで値を返しますよ」）とあるけど、`Go template` って何？

## TL;DR

```shell-session:ClientのArchを取得する
$ docker version --format '{{.Client.Arch}}'
amd64
$ docker version --format '{{.Client.Os}}'
darwin
```

## TS;DR

Docker の `version` コマンドで `Client` 欄に表示される情報を取得する Go テンプレート・フォーマット。

```shell-session:versionコマンドの内容
$ docker version
Client: Docker Engine - Community <------------- {{.Client.Platform.Name}}
 Version:           19.03.2 <------------------- {{.Client.Version}}
 API version:       1.40 <---------------------- {{.Client.APIVersion}}
 Go version:        go1.12.8 <------------------ {{.Client.GoVersion}}
 Git commit:        6a30dfc <------------------- {{.Client.GitCommit}}
 Built:             Thu Aug 29 05:26:49 2019 <-- {{.Client.BuildTime}}
 OS/Arch:           darwin/amd64 <-------------- {{.Client.Os}} {{.Client.Arch}}
 Experimental:      false <--------------------- {{.Client.Experimental}}
...
```

Docker の `version` コマンドで `Server` 欄に表示される情報を取得する Go テンプレート・フォーマット。

```shell-session
$ docker version
...

Server: Docker Engine - Community <---------------- {{.Server.Platform.Name}}
 Engine:
  Version:          19.03.2 <---------------------- {{.Server.Version}}
  API version:      1.40 (minimum version 1.12) <-- {{.Server.APIVersion}} {{.Server.MinAPIVersion}}
  Go version:       go1.12.8 <--------------------- {{.Server.GoVersion}}
  Git commit:       6a30dfc <---------------------- {{.Server.GitCommit}}
  Built:            Thu Aug 29 05:32:21 2019 <----- {{.Server.BuildTime}}
  OS/Arch:          linux/amd64 <------------------ {{.Server.Os}} {{.Server.Arch}}
  Experimental:     false <------------------------ {{.Server.Experimental}}
 containerd:
  Version:          v1.2.6 <----------------------- {{with (index .Server.Components 1)}}{{.Version}}{{ end }}
  GitCommit:        894b81a4b802e4eb2a91d1c... <--- {{with (index .Server.Components 1)}}{{.Details.GitCommit}}{{ end }}
 runc:
  Version:          1.0.0-rc8 <-------------------- {{with (index .Server.Components 2)}}{{.Version}}{{ end }}
  GitCommit:        425e105d5a03fabd737a126... <--- {{with (index .Server.Components 2)}}{{.Details.GitCommit}}{{ end }}
 docker-init:
  Version:          0.18.0 <----------------------- {{with (index .Server.Components 3)}}{{.Version}}{{ end }}
  GitCommit:        fec3683 <---------------------- {{with (index .Server.Components 3)}}{{.Details.GitCommit}}{{ end }}
```

### 全ての値を JSON 形式でダンプする（`raw`データのダンプ）

フォーマットを "`{{json .}}`" にすると JSON 形式で全体をダンプして取得できます。

```bash
docker version --format '{{json .}}' | jq .
```

```json
{
  "Client": {
    "Platform": {
      "Name": "Docker Engine - Community"
    },
    "Version": "19.03.2",
    "ApiVersion": "1.40",
    "DefaultAPIVersion": "1.40",
    "GitCommit": "6a30dfc",
    "GoVersion": "go1.12.8",
    "Os": "darwin",
    "Arch": "amd64",
    "BuildTime": "Thu Aug 29 05:26:49 2019",
    "Experimental": false
  },
  "Server": {
    "Platform": {
      "Name": "Docker Engine - Community"
    },
    "Components": [
      {
        "Name": "Engine",
        "Version": "19.03.2",
        "Details": {
          "ApiVersion": "1.40",
          "Arch": "amd64",
          "BuildTime": "Thu Aug 29 05:32:21 2019",
          "Experimental": "false",
          "GitCommit": "6a30dfc",
          "GoVersion": "go1.12.8",
          "KernelVersion": "4.9.184-linuxkit",
          "MinAPIVersion": "1.12",
          "Os": "linux"
        }
      },
      {
        "Name": "containerd",
        "Version": "v1.2.6",
        "Details": {
          "GitCommit": "894b81a4b802e4eb2a91d1ce216b8817763c29fb"
        }
      },
      {
        "Name": "runc",
        "Version": "1.0.0-rc8",
        "Details": {
          "GitCommit": "425e105d5a03fabd737a126ad93d62a9eeede87f"
        }
      },
      {
        "Name": "docker-init",
        "Version": "0.18.0",
        "Details": {
          "GitCommit": "fec3683"
        }
      }
    ],
    "Version": "19.03.2",
    "ApiVersion": "1.40",
    "MinAPIVersion": "1.12",
    "GitCommit": "6a30dfc",
    "GoVersion": "go1.12.8",
    "Os": "linux",
    "Arch": "amd64",
    "KernelVersion": "4.9.184-linuxkit",
    "BuildTime": "2019-08-29T05:32:21.000000000+00:00"
  }
}
```

## 参考文献

- [version](http://docs.docker.jp/engine/reference/commandline/version.html#version-examples) @ Docker 公式ドキュメント（日本語)
- [Access a map value using a variable key in a Go template
](https://stackoverflow.com/questions/26152088/access-a-map-value-using-a-variable-key-in-a-go-template#comment79909153_26152110) @ StackOverflow
- [GoのTemplateのPipelines(パイプライン)を理解しながら、テンプレート内で関数にスライスを引数で渡してみる](https://qiita.com/Sekky0905/items/fdbbad75d52e8336a6aa) @ Qiita