【Docker】【JavaScript】docker pull のレートリミットを素の Node.js だけで得る

 Docker は様々な仮想マシンを用いるためのソフトです。この様々な仮想マシンは自分で作るのみでなく DockerHub というところに大量に置かれています。この DockerHub から仮想マシン定義であるイメージを取得するのが常道なのですが、この DockerHub には以下のレートリミットがかかっており、過剰なイメージのダウンロードはできません。もし無制限にするならば課金の必要があります。
Docker Hub
Download rate limit | Docker Documentation
 具体的なレートリミットは次のアカウントの内容説明にあります。この記事を作った時点では以下です。
Docker Pricing & Monthly Plan Details | Docker

アカウント種類 レートリミット
匿名アカウント 100回 / 6時間
無料アカウント 200回 / 6時間
Pro 5000回 / 1日
Team 5000回 / 1日
この制限より更に上の制限を購入可能
Pro 5000回 / 1日
この制限より更に上の制限を購入可能

 制限があるとはいえ、個人で使うならば無料アカウントどころか匿名アカウントでも十分なくらいです(匿名アカウントはネットワーク単位で匿名ですので大人数で匿名で Docker を使う状況は足りなくなるやも)。とはいえレートリミットの残量が気になる時もあります。何がしかの理由で大量にダウンロードし、いざという時にダウンロードし過ぎと DockerHub に拒否される様な状況が起こると面倒なことになります。先述の Download rate limit のページにある API の利用によって具体的な残量を知れます。
 jq と curl が使える Linux マシンならばページにある次の 2 コマンドで十分です。

TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest

 このレスポンスが次の様になっており、レートリミット最大値(ratelimit-limit)とその残量(ratelimit-remaining)を知れます。

HTTP/1.1 200 OK
content-length: 2782
content-type: application/vnd.docker.distribution.manifest.v1+prettyjws
docker-content-digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
docker-distribution-api-version: registry/2.0
etag: "sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
date: Wed, 12 Jan 2022 07:38:29 GMT
strict-transport-security: max-age=31536000
ratelimit-limit: 100;w=21600
ratelimit-remaining: 80;w=21600
docker-ratelimit-source: 000.000.000.000

 よくある Docker 実行環境ならばこれで良いのですが Windows であったり、jq をインストールするのに許しが必要で申請が手間だったりする環境があります。そういった時、何がしかの代替手段が欲しくなります。Node.js を使って Docker のレートリミット残量を知るスクリプトは次で書けます。実行環境は Node.js 14.17.3 です。 https モジュールの基本機能しか使っていないので結構広い環境で使えそうな気がします。

const https = require('https');
// Node 組み込みの https モジュール でトークン取得 API を叩く
https.get(
  'https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull',
  (res) => {
    // トークン取得 API 結果をコールバックで処理
    res.on('data', (d) => {
      // トークン取得 API のレスポンスからトークン部を抜き出し
      const token = JSON.parse(d.toString()).token;

      // トークン取得APIの結果を受けて認証付きでレートリミット確認APIを実行
      https.get(
        `https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest`,
        {
          method: 'HEAD',
          headers: {
            Authorization: `Bearer ${token}`,
          },
        },
        (res) => {
          // 知りたい内容はヘッダーに格納されて送られてくるので次の様にレスポンスのヘッダーを表示
          console.log(res.headers);
        }
      );
    });
  }
);
/*
PS C:\xxx> node xxx.js
{
  'content-length': '2782',
  'content-type': 'application/vnd.docker.distribution.manifest.v1+prettyjws',
  'docker-content-digest': 'sha256:xxxx',
  'docker-distribution-api-version': 'registry/2.0',
  etag: '"sha256:xxxx"',
  date: 'Wed, 12 Jan 2022 08:15:01 GMT',
  'strict-transport-security': 'max-age=31536000',
  'ratelimit-limit': '100;w=21600',
  'ratelimit-remaining': '80;w=21600',
  'docker-ratelimit-source': '000.000.000.000',
  connection: 'close'
}
*/

 ヘッダーが実質的なレスポンスのボディのため少々奇妙なコードですが例の様に結果を得られます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG