Docker Hub のダウンロード数について

Docker Hub のダウンロード数はいつカウントアップされるのかを調査した。 オフィシャルな記載が見当たらなかったので、Download rate limit の記載を参考にしつつ、動作確認した(2021/6/9 時点)。

A pull request is defined as up to two GET requests on registry manifest URLs (/v2//manifests/).
A normal image pull makes a single manifest request.
A pull request for a multi-arch image makes two manifest requests.
HEAD requests are not counted.
引用元: Download rate limit

結論: /v2/*/manifests/* に GET リクエストを投げたときにカウントアップされる。 具体的には、イメージを push したときに 1 増える。 イメージを pull したときに 1 or 2 増える(適切なアーキテクチャを選択するために fat manifests を取得する場合は 2)。 イメージ A を FROM に指定した イメージ B がダウンロードされても、イメージ A のダウンロード数はカウントアップされない。

検証内容

イメージを push したとき

Docker Hub にアカウント作って適当なイメージ(kimullaa/parent)を push する。

FROM alpine:latest
RUN touch banana.txt

push した直後のダウンロード数は 1 になってた。

f:id:kimulla:20210609214623p:plain

イメージを pull したとき

docker pull すると、

# docker rmi -f $(docker images -aq)
# yes | docker system prune
# docker pull kimullaa/parent

ダウンロード数は 2 増えた。

f:id:kimulla:20210609214653p:plain

もちろん FROM に指定されているイメージをビルドするときも内部的には docker pull が走るので、ダウンロード数は 2 増えた。

# cat Dockerfile
FROM kimullaa/parent
RUN touch banana.txt
# docker build -t children -f Dockerfile .

f:id:kimulla:20210609214705p:plain

なお、イメージがすでにローカルに存在する場合はリモートアクセスが発生しないので、カウントアップされなかった。

f:id:kimulla:20210609214705p:plain

もっと細かく確認する

docker registry へのアクセスは HTTP を利用して行われることは以前調べた。

www.kimullaa.com

先述の late limit の記載に沿って、manifests(fat manifests と manifests 本体)を GET すると、ダウンロード数が増加した。以下、manifests の GET の実行例。

# token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:kimullaa/parent:pull" | jq -r '.token')
# curl -s -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' -H "Authorization: Bearer $token" "https://registry-1.docker.io/v2/kimullaa/parent/manifests/latest" | jq
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 1610,
    "digest": "sha256:4af74990d8a0c71580aa131fd15b1bd81a0c4f0ea6b2384919636bb2e7a30cb8"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 2811969,
      "digest": "sha256:540db60ca9383eac9e418f78490994d0af424aab7bf6d0e47ac8ed4e2e9bcbba"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 96,
      "digest": "sha256:1b559d233bdc82429f646110151b64f2617540daca6a8d630de3892a34d4d46a"
    }
  ]
}

ダウンロード数が 1 増えた。

f:id:kimulla:20210609214836p:plain

イメージ A を FROM に指定した イメージ B がダウンロードされたとき

実行前のダウンロード数

f:id:kimulla:20210609214901p:plain

# docker pull kimullaa/child

child を pull したあとのダウンロード数。child だけダウンロード数が増加した。

f:id:kimulla:20210609214931p:plain

なぜこうなるかというと、child の pull 時は child の config ファイルしか取得しないから(parent は child の config に記載された layer の URL に直接アクセスする)。

蛇足

しょぼいダウンロード数だとまともな値が見えるけど、メジャーなイメージだと、たいていは数が多すぎて 1B+ のような形で丸められている。

f:id:kimulla:20210609215359p:plain

API をたたくと、これの実際の値を知れる。1B+ だけど本当は 3.6B!26 億くらいは誤差!強い!

# curl -s https://hub.docker.com/v2/repositories/library/nginx/ | jq -r '.pull_count' | xargs printf "%'d\n"
3,689,137,505

API to read the pull counter - General - Docker Forums

まとめ

普通に docker pull するとたいていは +2 されるので、ダウンロード数はちょっと詐欺くさい。まああくまで目安だからいいけども。