GCPではContainer RegistryにDocker Imageを格納できる。格納したImageの取得にはdocker pullコマンドが使えるけど、時々Imageのメタデータだけを参照したいことがある。そういうとき、いちいちdocker pullするのは時間がかかるし、ストレージも食う。
そういう場合に、Imageのメタデータだけをうまく取れないか、ということで色々やってみたらできたので、そのメモ。Docker RegistryのAPI V2を使っているだけなので、たぶん他のプライベートレジストリの場合にもほぼ同じ方法でできる。
tl;dr
以下のコマンドを叩く。[project id], [repository name], [tag name or digest]は環境に合わせて置き換える。gcloud auth loginはしてある前提。
digest=$(curl -sL -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer $(gcloud auth print-access-token)" https://gcr.io/v2/[project id]/[repository name]/manifests/[tag name or digest] | jq -r .config.digest)
curl -sL -H "Authorization: Bearer $(gcloud auth print-access-token)" "https://gcr.io/v2/[project id]/[repository name]/blobs/${digest}" | jq .
以下でもう少し詳しく説明する。
1. まずはImage Manifestを取得する
Image Manifestは、Docker Imageを他の人と共有する際に必要な情報もろもろをまとめたもの。各Layerのハッシュ値や署名などが格納されている。仕様はここで確認できる。例えば以下のようなManifestが作られる。
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 32654,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
}
]
}
config.digestはconfigが格納されたblobのハッシュ値。このハッシュ値の指すblobを取得すると、Docker Container作成時につかうconfig情報が取れる。次のステップではこのblobを取得する。今回は使わないけど、layersにはDocker Imageのレイヤーごとの情報が入っている。
GCPのContainer RegistryからこのManifestを取得する場合、curlだと以下のコマンドでできる。
curl -sL -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer $(gcloud auth print-access-token)" https://gcr.io/v2/[project id]/[repository name]/manifests/[tag name or digest]
Registry APIを使っており、その仕様はここで確認できる。大事なのはHeaderでManifestのバージョンを指定するところ。これを忘れると古いバージョンのManifestを取得してしまう。
2. Configのblobを取得する
次にDocker Imageのconfig情報を取得する。今度もRegistry APIを使う。仕様はこのあたり。これを1で取得したblobのハッシュ値と組み合わせて、以下のように使う。
curl -sL -H "Authorization: Bearer $(gcloud auth print-access-token)" https://gcr.io/v2/[project id]/[repository name]/blobs/[configのblobのハッシュ値。sha256:文字列を含む]
例えば以下のような情報が取得できる。
{
"architecture": "amd64",
"config": {
"Hostname": "7e9ec6cde4d1",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOLANG_VERSION=1.8.1",
"GOLANG_DOWNLOAD_URL=https://golang.org/dl/go1.8.1.linux-amd64.tar.gz",
"GOLANG_DOWNLOAD_SHA256=a579ab19d5237e263254f1eac5352efcf1d70b9dacadb6d6bb12b0911ede8994",
"GOPATH=/go"
],
"Cmd": [
"/bin/bash"
],
"ArgsEscaped": true,
"Image": "sha256:c0ccf5f2c0365842c2a2faeb28e8058761e83832ebccf4c10558f106e88ab89e",
"Volumes": null,
"WorkingDir": "/go",
"Entrypoint": null,
"OnBuild": [],
"Labels": {
"key": "value"
}
},
...
}
環境変数やラベルなどが格納されている。僕の場合は、gitのcommit IDをラベルに格納しておいて、このIDが一致していたら云々、みたいな使い方をした。