docker 出来合いのコンテナを調査する際のTips

# Tips色々
オープンソース色々調査の関係で、dockerコンテナにまとめてくれているものベースで調査する機会が増えてきました。

最低限、dockerhubで該当のコンテナがそのオープンソースの開発会社が提供しているものであることの確認くらいはしてから使うのですが、ツール系では素性がよくわからないものも少なからず出てきます。
あるいは、ちょっとややこしい使い方をしようとする際にコンテナ内部の作りを把握したいとか。
そんなときに使うTipsをメモっておきます。

# 1. コンテナの素性に関するTips
誰が作ったか、どのディストリのイメージをベースにしているか、の２点はまずざっくり把握しておきたいところです。
dockerhubで調査するのも面倒ですし、コマンドベースで調べる方法がないかな、、ということで調べてみましたが、結論、いい方法見つけられませんでした。
今回の調査では、ちょうど別件で調査中だったgrafana/promtailを題材にしてみます。

## コンテナの開発者情報
結論から言うと、dockerhubのサイトを見てリンクをたどるしかなさそうです。

できそうな方法もありますが、、、

```
% docker image inspect grafana/promtail | grep Author
        "Author": "",
```

はい。
ちなみに、archlinuxもubuntuも一緒でした。

別の方法で思いつくのは、、、

```
% docker search promtail
NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
noenv/promtail                   Promtail Docker Image                           0                    
kathrynzhou/promtail             Promtail Docker Image                           0                    
arangodboasis/promtail-sidecar   Promtail sidecar helper                         0                    
randomcoww/promtail              Smaller promtail image without systemd suppo…   0                    
410labs/promtail                 based on the official grafana/promtail image…   0                    
certascale/promtail                                                              0                    
mylabtools/promtail              Preconfigured Promtail for Grafana Loki         0                    
aporeto/promtail                                                                 0                    
findify/promtail                                                                 0                    
kausal/promtail                                                                  0                    
odinuge/promtail                                                                 0          
```

。。。ん？
公式っぽいgrafana/promtailがそもそもひっかかってない、、？
検索結果の表示数が足りてなく表示外になってしまっているのかもしれませんが、searchのあとの引数を"grafana/promtail"にしてもヒットなし。
というか、/が入ると検索がうまくいかなくなるっぽいです。
仮にヒットしても、公式な作者情報が出てくるわけじゃないので、この方法ではだめですね。

dockerhubのサイトで確認するしかなさそうですね。。

## コンテナの親子関係の確認方法
これも、結論としては、dockerhubから初めて探し回って、githubにおいてあるDockerfileをみつけるしかなさそうです。

それっぽいツールとしてはこのようなものがあるのですが、、
https://github.com/justone/dockviz

docker.sockから自分のdocker環境に展開しているコンテナ郡の情報の詳細を引き抜いて、親を追いかけていくみたいです。
パイプでdockvizに食わせる方法も紹介されており、その際のデータがこちら。

```
%  echo -e "GET /images/json?all=1 HTTP/1.0\r\n" | nc -U /var/run/docker.sock | tail -n 1 | jq -C | less -R
  {
    "Containers": -1,
    "Created": 1642924455,
    "Id": "sha256:6d9dfbba78f8a90fc32fc5275a4064bc00d9f7c475daf8ef7cf1706cab2d1531",
    "Labels": null,
    "ParentId": "sha256:de897944d1cbea90020fcb62862097bb265aec7ddf7a6431f2f24d800a46d0d8",
    "RepoDigests": [
      "<none>@<none>"
    ],
    "RepoTags": [
      "<none>:<none>"
    ],
    "SharedSize": -1,
    "Size": 382423382,
    "VirtualSize": 382423382
  },
  {
    "Containers": -1,
    "Created": 1642924454,
    "Id": "sha256:de897944d1cbea90020fcb62862097bb265aec7ddf7a6431f2f24d800a46d0d8",
    "Labels": null,
    "ParentId": "sha256:9f9b229575b2cb787cf104f4706142dcba61af1ed63f045e3bf7204a721de15f",
    "RepoDigests": [
      "<none>@<none>"
    ],
    "RepoTags": [
      "<none>:<none>"
    ],
    "SharedSize": -1,
    "Size": 382423382,
    "VirtualSize": 382423382
  },
  {
    "Containers": -1,
    "Created": 1642530010,
    "Id": "sha256:9f9b229575b2cb787cf104f4706142dcba61af1ed63f045e3bf7204a721de15f",
    "Labels": null,
    "ParentId": "",
    "RepoDigests": [
      "archlinux@sha256:09cb5c65e147de3999f8b4ebf0eff04dfaeaab0726a1c1d896c48add98390841"
    ],
    "RepoTags": [
      "archlinux:latest"
    ],
    "SharedSize": -1,
    "Size": 382423382,
    "VirtualSize": 382423382
  },
```

ローカルに落としてきているimageベースでの調査ですね。
これで、大本になっているLinuxのディストリが特定できるかというと、、できません。
例えば、自分がローカルでarchlinuxをFromしてイメージをbuildした場合はarchlinuxまでたどれますが、出来合いのコンテナイメージをpullした場合、一番の親になっているイメージはbuild時の最初の部分の処理をしたあとのイメージになっていて、それがベースにしたディストリのイメージになっているわけじゃないんですね。。

ということで、残念ながら該当のコンテナイメージの祖先（なんのディストリを使っているか/ベースのイメージがなにか）の調査には使えませんでした。。

ちなみに、dockvizのRunningの後で紹介されている、上記のようにホスト側で引き抜いた情報をパイプでdockvizコンテナに渡す方法ではうまく行かず、socketを仮想マシンにマウントする方法をとらないとだめっぽいです。
あと、そもそも、このツールと製作者の方の素性を追いきれていないです。

/images/jsonのデータをたどるという概念だけ参考にさせていただきます。

# 2. コンテナの内部の作りに関するTips
素性はなんとなく把握した（あるいは深追い諦めた）として、それはそれで、イメージの中でどのようなパッケージやライブラリを使っているのかは把握しておきたいところです。
そこら編の調査に関するTIPSです。

## Dockerfileの調査
この方針は、安定した方法が見つけられずにいます。。。

DockerHubからわかるのはここまで。
Dockerfileを公開しているのではなくて、Imageレイヤ毎のコメントだけまとめている、、という感じでしょうか。

![20220130_12h45m20s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/33a021b3-35f8-93e5-a90b-0e4401397976.png)

ありがたいケースだと、dockerhubのDescriptionページなんかにgitへのリンクが貼ってあって、そちらにDockerFileがおいてあるのですが、ないものはないです。
grafana/promtailはリンクもないのですが、そもそもgrafanaアカウントのgithubを調べても、それっぽいものを見つけられませんでした。

そういう場合は、ダウンロードしてきて実態で調べるということをしないといけません。。。

## Imageに含まれるファイル群を閲覧する
ホストマシンにoverlay2をマウントする方法で実施できます。

dockerはディフォの設定だと、/var/lib/docker/overlay2の配下に配置されます。
詳細は以下。
https://docs.docker.jp/engine/userguide/storagedriver/overlayfs-driver.html

cdなりtreeなりして中除けば大体把握はできるのですが、レイヤ構造になっているため変更かけているファイルが別のディレクトリに入っていますので、微妙に見づらいです。

コンテナ起動してしまえば統合されますし、その前提で調べるのが次に記載する方法ですが、それはそれとして、コンテナを起動しないでデータを確認する方法を用意しておきたいところです。

で、方法としてはこちら。
https://wiki.archlinux.jp/index.php/Overlayfs
対象はまたgrafana/promtailを使わせていただきます。

```
$ mkdir tmpdir
# mount -t overlay overlay -o ro,$(docker image inspect -f "lowerdir={{.GraphDriver.Data.LowerDir}},upperdir={{.GraphDriver.Data.UpperDir}},workdir={{.GraphDriver.Data.WorkDir}}" grafana/promtail) ./tmpdir
```

間違えてうわがいてしまうと少々めんどくさいので、read only(ro)をつけています。
これでコンテナの中のファイルが全部見えますので、etc配下を探ってディストリの辺りをつけたり、entrypointで指定されているスクリプトの中身を確認したり、ということができるようになります。

終わったら、umount。

## エントリーポイントを上書きしてログインしてみる
最後の手段、、でしょうか。
コンテナとして起動し続けてくれるタイプであれば、execを使って起動中のコンテナに横入りする、という手を使えるのですが、適切な引数がない場合にすぐ動作を終了してしまうコンテナの場合はexecの方法が取れません。
そういう場合のための方法です。

```
$ docker run -it --entrypoint="/bin/sh" grafana/promtail
```

上記は、"/bin/shは流石に持ってるだろ、、”と当たりをつけて実施していますが、/bin/shがないようなケースもあるかもしれません。
そういうときはoverlay2をマウントする方法まで、ですね。。

ちなみに、コンテナが起動し続けてくれているなら、以下でOKです。

```
$ docker exec it <cotainer> /bin/sh
```

以下だと、だいたいだめです。

```
$ docker run -it grafana/promtail /bin/sh
```

コンテナにエントリーポイントが定義されていない場合はこれでも通るのですが、エントリポイント指定がある場合は、エントリポイントのスクリプトやプログラムに”/bin/sh"という引数を与えるという処理になるので、意図した動作にならないので。

# まとめ
コンテナの中身を調査するときの泥臭いTipsをまとめました。
おそらくまた調査していくとネタが出てくると思いますので、そしたら「その２」でも書こうかなと思います。