docker search
コマンドで,Docker Hubのイメージ名を検索できます。しかし,そのイメージにどのようなタグがあるのかを調べる方法は用意されていません。そこで,Docker Hubのイメージのタグ一覧を取得するコマンドを作ってみましょう。
本記事ではそのコマンドを構築する過程を解説しますが,手っ取り早く完成形を見たい人は,記事の一番下に飛んでください。
API v1 は停止されている
「Docker Hubのタグ一覧を取得するには」といった内容でGoogle検索すると,
https://registry.hub.docker.com/v1/repositories/<イメージ名>/tags
というURLの HTTP API に curl
でアクセスする方法がよくヒットします。しかし,Docker Hub の API v1 は2022年を最後に停止されており,現在ではこの方法は使えません。
API v2 を使う方法(※個数制限あり)
次に,API v2 を使う簡単な方法を調べてみると,
https://hub.docker.com/v2/repositories/<ネームスペース名>/<イメージ名>/tags?page_size=100
というURLにアクセスして得られるJSONをパースする方法がヒットします。<ネームスペース名>
の部分は,公式イメージならば library
, 個々のユーザのイメージの場合はユーザ名を指定します。例えば Ubuntu の公式イメージのタグをリストアップするのであれば,
curl -s "https://hub.docker.com/v2/repositories/library/ubuntu/tags?page_size=100"
としてアクセスすると,
{
"count": 621,
"next": "https://hub.docker.com/v2/repositories/library/ubuntu/tags?page=2&page_size=100",
"previous": null,
"results": [
{
"creator": 7,
"id": 2343,
"images": [
(中略),
"name": "latest",
(後略)
というJSONが得られます。これをjq
でパースし,キー "name"
に対応する値を取り出せば取り出せばよいというわけです。
そのために,次のように jq -r '.results[].name'
にパイプで渡しましょう。
curl -s "https://hub.docker.com/v2/repositories/library/ubuntu/tags?page_size=100" | jq -r '.results[].name'
すると,確かにタグのリストが得られます。
jq
がインストールされていないシステムの場合,apt
や brew
, port
といったパッケージ管理コマンドでインストールするのが一手です。ソースコードからコンパイルするのもお手軽です。その方法は次の記事で示しました。
問題点:個数100個制限
ただし,この方法には問題点があります。URLの ?page_size=100
というクエリ文字列に現れているように,このURLにアクセスすると,100個までしかタグを取得できません。ならばこの100
をもっと大きい数字に指定すればよいのでは,と思われるでしょうが,この数字は最大値が100であり,これ以上大きな値を指定しても100個で止められてしまいます。
先程のJSONの返値に
"count": 621,
"next": "https://hub.docker.com/v2/repositories/library/ubuntu/tags?page=2&page_size=100"
という行があります。これは,
- 全部で621個ある
- 次の100個を見るにはこのURLにアクセスしてね
ということを意味しています。よって,「次のURL指定があればそこにアクセスする」という行為を繰り返せば,全部のタグを取得できることになります。
しかし,そのような判定&反復を行うスクリプトを書くのは若干手間がかかりますし,HTTPアクセスを無用に繰り返すことになるのは何とも筋が悪いです。何とかして,全部のタグを一括取得する方法はないでしょうか。
API v2 で全タグを一括取得するには(個数制限なし)
個数制限なくタグを一括取得する方法は,次の記事に調査結果がまとめられています。
この記事での調査結果に基づくと,Docker Hub のイメージのタグ名を取得するには,
- まず
https://auth.docker.io/token?scope=repository%3A<ネームスペース名>%2F<イメージ名>%3Apull&service=registry.docker.io
に取得してtoken
を取得する。このトークンは300秒間有効。 - 次に HTTP のリクエストヘッダに
Authorization: Bearer <得られたトークン>
を付け加えた上で,https://registry-1.docker.io/v2/<ネームスペース名>/<イメージ名>/tags/list
というURLに対して HTTP GET Request を投げると,タグの一覧がJSONとして返ってくる。
となっています。curl
と jq
を駆使してそのようなアクセスをするには,次のようにします。
export NAMESPACE=library
export IMAGE=ubuntu
curl -s -H "Authorization: Bearer $(curl -s "https://auth.docker.io/token?scope=repository%3A${NAMESPACE}%2F${IMAGE}%3Apull&service=registry.docker.io" | jq -r '.token')" "https://registry-1.docker.io/v2/${NAMESPACE}/${IMAGE}/tags/list" | jq
{
"name": "library/ubuntu",
"tags": [
"10.04",
"12.04",
"12.04.5",
(後略)
という形のJSONが得られるので,これを jq -r '.tags[]'
で抽出すれば,タグのリストを一括で取得できる,というわけです。
API v2 でイメージの対応CPUアーキテクチャを調べるには
Apple Silicon Mac を使っている場合などには,各イメージの対応CPUアーキテクチャが気になります。イメージは amd64
のみ対応というケースが多いので,Apple Silicon ユーザの場合は arm64
に対応しているかどうかに関心を持つケースが多いでしょう。
対応アーキテクチャを調べるには,イメージのマニフェストを調べる必要があります。API ドキュメントによれば,イメージの マニフェストは次の方法で取得できることが分かります。
- まず
https://auth.docker.io/token?scope=repository%3A<ネームスペース名>%2F<イメージ名>%3Apull&service=registry.docker.io
に取得してtoken
を取得する。このトークンは300秒間有効。 - 次に HTTP のリクエストヘッダに
Authorization: Bearer <得られたトークン>
を付け加えた上で,https://registry-1.docker.io/v2/<ネームスペース名>/<イメージ名>/manifests/<タグ名>
というURLに対して HTTP GET Request を投げると,manifest がJSONとして返ってくる。
2パターンのマニフェストJSONに注意
docker build
でビルドされた単一アーキテクチャイメージと,docker buildx
でビルドされたマルチアーキテクチャイメージでは,返ってくるマニフェストJSONの構造が異なるため,その後のJSONのパースにおいて注意が必要です。
単一アーキテクチャイメージの場合
{
"schemaVersion": 1,
"name": "mysql/mysql-server",
"tag": "latest",
"architecture": "amd64"
(後略)
このように,素直に直下に "architecture"
というキーがあるので,その値を jq -r '.architecture'
で取り出せば済みます。
マルチアーキテクチャイメージの場合
{
"manifests": [
{
"digest": "sha256:28a2b328825ac02db5c29d9356bfba80ba6c4b6ebfcac5a91a4656fa3453775a",
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"platform": {
"architecture": "amd64",
"os": "linux"
},
"size": 424
},
{
"digest": "sha256:c94d54dd82aba50b58c698accfc4a0a849955ba93f3a1de76353326caf2e9229",
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
},
"size": 424
},
(後略)
というように,各アーキテクチャ用イメージのマニフェストがリストで並んできます。これをパースして "architecture"
の値だけを取り出すには,jq -r '.manifests[].platform.architecture'
で抽出する必要があります。
両方のパターンに対応するため,
jq -r '.architecture // .manifests[].platform.architecture'
でフィルタすることにしましょう。
完成形
こうして完成した手法を,シェル関数の形でまとめました。
シェル関数のソース
使い方
1. docker-list-tags
関数:全タグのリストアップ
docker-list-tags
関数を指定します。引数には,公式イメージならばイメージ名のみ,各ユーザに属するイメージの場合は ユーザ名/イメージ名
を指定します。
docker-list-tags ubuntu
docker-list-tags mysql/mysql-server
オプション
-
-n
,--with-name
: デフォルトでは22.04
のようにタグ名だけを出力しますが,このオプションを付けると,ubuntu:22.04
のようにイメージ名を付けた出力になります。 -
-j
,--json
: タグ一覧を改行区切りテキストではなく,JSONとして出力します。出力結果をjq
でさらに加工したい場合に使えます。
2. docker-inspect-architecture
関数:対応CPUアーキテクチャの調査
次のような書式で指定します。タグ名を略した場合は :latest
が補われます。マルチアーキテクチャイメージの場合は対応する全アーキテクチャが列挙されます。
docker-inspect-architecture ubuntu
docker-inspect-architecture ubuntu:22.04
docker-inspect-architecture mysql/mysql-server
docker-inspect-architecture mysql/mysql-server:8.0