コンテナイメージの情報をシンプルに確認するツールdockertags

# はじめに

公式のコンテナイメージを利用していると、いまどんなOS,バージョンのイメージが使えるのか知りたいときがあります。そんなときに使えるツールを作りました。(Golangで書いてます)
![image](https://github.com/goodwithtech/dockertags/raw/master/assets/usage.gif)
https://github.com/goodwithtech/dockertags [![stars](https://img.shields.io/github/stars/goodwithtech/dockertags.svg)](https://github.com/goodwithtech/dockertags)
(たぶんこのままだとstarが一個もつかないので気がついた人はstarください)

たとえばgolang 1.14のイメージ、alpineベースで探したいときは、以下のように指定できます。

```
$ dockertags -c 1.14 -c alpine golang
+----------------------+--------+----------------------+-------------+
|         TAG          |  SIZE  |      CREATED AT      | UPLOADED AT |
+----------------------+--------+----------------------+-------------+
| 1.14beta1-alpine3.10 | 128.3M | 2019-12-18T03:25:01Z | NULL        |
| 1.14beta1-alpine     | 128.3M | 2019-12-18T03:24:58Z | NULL        |
| 1.14-rc-alpine3.10   | 128.3M | 2019-12-18T03:24:16Z | NULL        |
| 1.14-rc-alpine       | 128.3M | 2019-12-18T03:24:11Z | NULL        |
+----------------------+--------+----------------------+-------------+
```


また、各種プライベートレジストリにも対応してます。
CIで最新のビルドイメージのタグを特定して、そのイメージに対して処理をおこなうことができます。イメージに対してスケジュールを組んで、脆弱性チェックをしたいときに役立ちます。

たとえば、以下のコマンドを実行すると、指定したイメージの最新のバージョンを、[aquasec/trivy](https://github.com/aquasecurity/trivy)でスキャンすることができます。

```shell
$ export IMAGENAME=<imagename>
$ trivy $IMAGENAME:$(dockertags -limit 1 -format json $IMAGENAME | jq -r .[0].tags[0])

==================================
Total: 4 (UNKNOWN: 0, LOW: 1, MEDIUM: 2, HIGH: 1, CRITICAL: 0)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| musl    | CVE-2019-14697   | HIGH     | 1.1.20-r4         | 1.1.20-r5     | musl libc through 1.1.23       |
|         |                  |          |                   |               | has an x87 floating-point      |
|         |                  |          |                   |               | stack adjustment imbalance,    |
|         |                  |          |                   |               | related...                     |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| openssl | CVE-2019-1549    | MEDIUM   | 1.1.1b-r1         | 1.1.1d-r0     | openssl: information           |
|         |                  |          |                   |               | disclosure in fork()           |
+         +------------------+          +                   +               +--------------------------------+
|         | CVE-2019-1563    |          |                   |               | openssl: information           |
|         |                  |          |                   |               | disclosure in PKCS7_dataDecode |
|         |                  |          |                   |               | and CMS_decrypt_set1_pkey      |
+         +------------------+----------+                   +               +--------------------------------+
|         | CVE-2019-1547    | LOW      |                   |               | openssl: side-channel weak     |
|         |                  |          |                   |               | encryption vulnerability       |
+---------+------------------+----------+-------------------+---------------+--------------------------------+

```

# 基本の使い方

## Homebrew (Mac / Linux)
```shell
$ brew install goodwithtech/r/dockertags
$ dockertags [IMAGE_NAME]
```

## Docker経由

```shell
$ VERSION=$(
 curl --silent "https://api.github.com/repos/goodwithtech/dockertags/releases/latest" | \
 grep '"tag_name":' | \
 sed -E 's/.*"v([^"]+)".*/\1/' \
) && docker run --rm goodwithtech/dockertags:v${VERSION} [IMAGE_NAME]
```

## 出力結果

指定したイメージに紐づく情報(タグ,サイズ,更新日)が、新しい順に並びます。

```
+--------------------+-------+----------------------+-------------+
|        TAG         | SIZE  |      CREATED AT      | UPLOADED AT |
+--------------------+-------+----------------------+-------------+
| nanoserver-1809    | 94.5M | 2019-12-10T23:41:41Z | NULL        |
| nanoserver         | 94.5M | 2019-12-10T23:41:37Z | NULL        |
| linux              | 94.5M | 2019-12-10T23:41:33Z | NULL        |
| latest             | 94.5M | 2019-12-10T23:41:26Z | NULL        |
| nanoserver-1803    | 94.5M | 2019-11-20T14:41:37Z | NULL        |
| nanoserver-1709    | 94.5M | 2019-04-12T05:43:34Z | NULL        |
| nanoserver-sac2016 | 94.5M | 2019-01-01T10:43:20Z | NULL        |
| nanoserver1709     | 94.5M | 2017-11-21T05:43:32Z | NULL        |
+--------------------+-------+----------------------+-------------+
```

# 応用例

## 最新10件だけ取得

```
$ dockertags -l 10 golang
+--------------------------------------+--------+----------------------+-------------+
|                 TAG                  |  SIZE  |      CREATED AT      | UPLOADED AT |
+--------------------------------------+--------+----------------------+-------------+
| rc-windowsservercore-ltsc2016        | 5.5G   | 2019-12-18T03:25:54Z | NULL        |
.... 中略 ...
| rc-alpine                            | 128.3M | 2019-12-18T03:25:33Z | NULL        |
| rc                                   | 297.3M | 2019-12-18T03:25:29Z | NULL        |
| 1.14beta1-windowsservercore-ltsc2016 | 5.5G   | 2019-12-18T03:25:18Z | NULL        |
+--------------------------------------+--------+----------------------+-------------+
```


## 指定の文字列を含んだものだけ取得 (複数指定可)

`alpine`、 `1.13`を含んだものから新しいものを10件表示

```
$ dockertags -l 10 -c alpine -c 1.13 golang
+----------------------+--------+----------------------+-------------+
|         TAG          |  SIZE  |      CREATED AT      | UPLOADED AT |
+----------------------+--------+----------------------+-------------+
| 1.13.5-alpine3.10    | 123.9M | 2019-12-06T00:28:57Z | NULL        |
| 1.13.5-alpine        | 123.9M | 2019-12-06T00:28:52Z | NULL        |
| 1.13-alpine3.10      | 123.9M | 2019-12-06T00:28:28Z | NULL        |
...
```

## JSON形式で出力

```
$ dockertags -l 2 -c alpine -f json golang
[
  {
    "tags": [
      "rc-alpine3.10"
    ],
    "byte": 134524340,
    "created_at": "2019-12-18T03:25:37.9831Z",
    "uploaded_at": "0001-01-01T00:00:00Z"
  },
  {
    "tags": [
      "rc-alpine"
    ],
    "byte": 134524340,
    "created_at": "2019-12-18T03:25:33.233289Z",
    "uploaded_at": "0001-01-01T00:00:00Z"
  }
]
```

# プライベートレジストリへの認証

Docker Hub, Amazon ECR, GCR のプライベートレジストリに対応しています。
認証情報を環境変数などで指定すれば、操作方法は同じです。

```
# 認証に必要な情報を入れる
$ export AWS_PROFILE=XXXXX
$ dockertags xxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/api-streaming
+------------------------------------------+-------+------------+----------------------+
|                   TAG                    | SIZE  | CREATED AT |     UPLOADED AT      |
+------------------------------------------+-------+------------+----------------------+
| e3a27f568d767c262deb1e22214024095a91a28a | 61.3M | NULL       | 2019-11-20T11:41:02Z |
| 2f0690dddc12c47ca5f407bfa7f24ef4bfda49be | 61.3M | NULL       | 2019-09-17T06:22:24Z |
| ab192f7826efe21362775a04265bebc22715bba5 | 61.2M | NULL       | 2019-08-19T05:45:58Z |
| e5e5f67dc5aa6bf317dc84a48805fe0c70e4d789 | 61.2M | NULL       | 2019-06-24T14:43:55Z |
| 30b5f664ba75d4ee35ceee28c3ed6f975483be43 | 61.2M | NULL       | 2019-06-11T17:02:40Z |
| e7554a8d3247502d41ef96e1d866dac578249c55 | 61.2M | NULL       | 2019-05-10T14:41:37Z |
| 00a5e3db0d0880f06e7921aee0b4cd97f77c2d9b | 60.5M | NULL       | 2019-04-02T11:58:13Z |
| 756465066665054022fa9ad59ad3e7a6173fb683 | 60.5M | NULL       | 2019-04-02T07:42:46Z |
| 0677d9d210a37efd3677ca175b8326f5d67182a2 | 60.5M | NULL       | 2019-03-22T17:09:01Z |
+------------------------------------------+-------+------------+----------------------+

```

# 裏側の実装

Docker RegistryのAPI仕様書というものが存在するんですが、実はデフォルトの仕様だと、タグ一覧は取得できますが、作成日やサイズなどは返ってきません。

[Docker Registry HTTP API V2](https://github.com/docker/distribution/blob/5cb406d511b7b9163bff9b6439072e4892e5ae3b/docs/spec/api.md)
> ### Listing Image Tags
> It may be necessary to list all of the tags under a given repository. The tags for an image repository can be retrieved with the following request:
> `GET /v2/<name>/tags/list`
> The response will be in the following format:
> 200 OK
> Content-Type: application/json
>`{
>     "name": <name>,
>     "tags": [ <tag>... ]
>}`

そのため、レジストリごとに別の方法でデータを取ってきています。

# まとめ

この機能は｢[FutureVuls](https://vuls.biz/)｣という、脆弱性管理ツールに組み込まれていて、最新のタグを動的に取得するときに利用されています。興味ある方はデモなどでご確認ください。
https://releasenote.vuls.biz/release-note/20191217/

そして、Star数伸びないのは分かっていながら、めちゃくちゃニッチな機能をがんばってつくりました。 ということで、Starください。
https://github.com/goodwithtech/dockertags [![stars](https://img.shields.io/github/stars/goodwithtech/dockertags.svg)](https://github.com/goodwithtech/dockertags)