docker pullのRate Limits適用状態を確認

# 概要

[2020年11月2日から実施と発表のあった](https://www.docker.com/blog/what-you-need-to-know-about-upcoming-docker-hub-rate-limiting/)、docker pull の Rate Limits（ダウンロードレート制限）について、コマンドライン上で適用状態が確認する方法が、[Docker Blogに掲載](https://www.docker.com/blog/checking-your-current-docker-pull-rate-limits-and-status/)されていました。これを実際に試した記録です。

ポイント

- 認証(docker login）していない場合、サーバへのログイン数に関係なく、すべてが anonymous（非認証）という単位でカウントされる。そのため、2人が同時に50 pullを走らせると、Rate Limitに到達する場合が有り得る
- 同じサーバ上でも、認証しているアカウントと、認証していないアカウントでの制限は別にカウントされるので、認証している場合は他人の影響を受けない模様

## Docker Pull Rate Limits について

8月24日に[Dockerから発表](https://www.docker.com/blog/scaling-docker-to-serve-millions-more-developers-network-egress/)された通り、pull時のダウンロード比率の制限が11月2日から変更となる模様です。

- 認証していない（anonymous ユーザ）場合は、100ダウンロード/6時間
- 認証している場合（Free アカウント）は 200 ダウンロード/6時間
- Docker Pro / Team 有償アカウントでログイン時は無制限


最新の制限状態については、以下のページで公開されています。

- Understanding Docker Hub Rate Limiting
  - https://www.docker.com/increase-rate-limits

> Current Docker Hub Usage Limit Status (updated 11/2, 9:00am Pacific)
> Unauthenticated requests:	5,000 per six hours
> Free tier requests:	5,000 per six hours

- 現時点（11/2 日本時間8:00)では、認証している場合・いない場合も 5,000 リクエスト/6 時間
  - ※ただし Pacific Time 11/2 9:00（日本時間11/3 9:00）に改訂予定

> Temporary full enforcement window (100 per six hours for unauthenticated requests, 200 per six hours for free accounts): November 2, 9am-10am Pacific Time. 

- 一時的に 11/2 9:00～10:00(PT) （日本時間11/3 2:00～3:00)にかけて、非認証 100/6時間、認証 200/6時間に強制制限（ "Temporary" ということは、続くのではなく、一時的な強制措置？）

## Rate Limit を確認する

Rate Limit を検証するための方法が、Docker ブログに掲載されています。

- Checking Your Current Docker Pull Rate Limits and Status - Docker Blog
  - https://www.docker.com/blog/checking-your-current-docker-pull-rate-limits-and-status/

これは `ratelimitpreview/test` というイメージを `pull` するコマンドを実行することで、擬似的に Rate Limit が適用されることを確認するものです。

ただし、ブログ中にも記載がありますが、リクエストを実行するコマンド実行は、実際に Docker Hub に対してリクエスト（ `pull` ）を送っている場合、当然ながらコマンド実行そのものがカウント対象となりますのでご注意ください。


### 事前準備

- `jq` は必須 （ CentOS なら `yum install jq` ）
- 細かくデータを見たい場合は、`base64` など、必要に応じて jwt を処理できるコマンドラインツール

### 具体的な確認

#### Anonymous でリクエストをテストする方法

Docker の入っている環境上で、このコマンドを実行。

```
$ TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
```

それから

```
curl -v -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep -i ratelimit
< ratelimit-Limit: 100;w=21600
< ratelimit-Remaining: 99;w=21600
< docker-ratelimit-source: IPアドレス
   "name": "ratelimitpreview/test",
```

と実行すると、現在の制限（Limit）が `100` 、そして 残り（ratelimit-Remaining）が `99` になっているのが分かる。また、対象のソースアドレスが docker-ratelimit-source 列にも表示

何度か `docker pull` コマンドを実行しててダウンロードを続けると、

```
$  curl -v -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep rateLimit
< rateLimit-Limit: 100;w=21600
< rateLimit-Remaining: 95;w=21600
```

となり、`rateLimit-Ramaining` が `95` に減少しているのが分かる。

#### 認証してテストする方法

2行目「username」「password」はDocker Hubログイン時のものを入力する。

```
$ HISTCONTROL=ignorespace
$  TOKEN=$(curl --user 'username:password' "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
```

Token取得後は、先ほどの anonymous と同じように確認できる。

```
curl -v -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep rateLimit
< rateLimit-Limit: 200;w=21600
< rateLimit-Remaining: 198;w=21600
```

なお、単純に現在適用されている Rate を確認するには、 `$TOKEN` の中身を `jwt` (JSON Web Token) を扱えるツールなどを使うか、コマンドラインであれば

```
$ for line in `echo -n $TOKEN | tr "." "\n"`; do echo -n $line | base64 -d 2>/dev/null | jq  2>/dev/null && echo;done
```

を実行し、以下の `pull_limit` や `pull_limit_interval` からも確認できる。

```json

{
  "access": [
    {
      "type": "repository",
      "name": "ratelimitpreview/test",
      "actions": [
        "pull"
      ],
      "parameters": {
        "pull_limit": "200",
        "pull_limit_interval": "21600"
      }
    }
  ],
```

## メモ

普通に個人が使っている分には問題なさそうだけれども、CIを anonymous でまわしているような環境や、PROXY やゲートウェイを通すような環境などで、1箇所からのアクセスが短時間に集中すると（認証がなければ）影響を受けるかもしれない。