2022年11月6日日曜日

docker-registry-proxy でコンテナイメージをキャッシュする

色々実験していると、各種 Container Registry のレートリミットが怖くなってくるので、ローカルにキャッシュサーバーを建てることにした。

ただ、Dockerfile や Manifest 内のイメージ URL を変更するのは辛いので、透過的にキャッシュを取得する方法を実現したい。

apt-cacher-ng を知っている方は、「それのコンテナイメージ版が欲しい」という感じで理解していただければ OK。

rpardini/docker-registry-proxy が、Man in the Middle 方式でキャッシュしてくれるようなので、それを試す。

前提

  • OS: Windows 11 Pro 21H2 ビルド 22000.1042
  • Docker Desktop: 4.12.0 (85629)

docker-registry-proxy のコンテナを起動

今回は、Docker Compose で建てることにした。 以下 yaml ファイルを作成し、 docker compose up -d する。

version: '3'

services:
  docker-registry-proxy:
    image: rpardini/docker-registry-proxy:0.6.4
    restart: always
    environment:
      # k8s のマニフェストキャッシュ機能を有効化
      ENABLE_MANIFEST_CACHE: true
      # `registry-1.docker.io` 以外にキャッシュしたいレジストリをスペース区切りで記載
      REGISTRIES: "k8s.gcr.io gcr.io quay.io"
    volumes:
      # キャッシュデータ格納用ディレクトリ
      - docker-registry-proxy:/docker_mirror_cache
      # 証明書関連データ格納ディレクトリ
      - docker-registry-proxy-ca:/ca
    ports:
      - 0.0.0.0:3128:3128
volumes:
  # キャッシュデータ格納用ボリューム
  docker-registry-proxy:
    name: docker-registry-proxy
  # 証明書関連データ格納ボリューム
  docker-registry-proxy-ca:
    name: docker-registry-proxy-ca

Windows の設定

ファイアウォールに穴をあける

今回は、同じネットワークの他ホストからも参照させたいので、 TCP 3128 の受信を許可する。

docker-registry-proxy の証明書インストール

docker-registry-proxy の Web サーバーから取得できるので、 Invoke-WebRequest で取得して、 Import-Certificate でインストールする。

# docker-registry-proxy の証明書を取得
Invoke-WebRequest -Uri http://localhost:3128/ca.crt -OutFile ca.crt

# 取得した証明書を Windows に、 `信頼されたルート証明機関` としてインストール。
Import-Certificate -FilePath .\ca.crt -CertStoreLocation Cert:\CurrentUser\Root

セキュリティ警告 のダイアログが出て、 この証明書をインストールしますか? と聞かれるので はい(Y) を押下。

証明書のインストール後、 Docker Desktop を再起動する。

Docker Engine の設定

プロキシ設定

  1. タスクトレイの Docker アイコン右クリック -> Settings -> Resources -> Proxies と選択し、必要な設定を入力後、 Apply & Restart ボタンを押下
    • Manual proxy configuration: オンにする
    • Web Server (HTTP):http://localhost:3128`
    • Web Server (HTTPS):http://localhost:3128`

docker info コマンドで、プロキシ設定が有効になっていることを確認できる。

Docker Desktop 再起動

Apply & Restart では、証明書の再読み込みまでしてくれないらしいので、 Docker Desktop の再起動を行う。

タスクトレイの Docker アイコン右クリック -> Restart 押下。

動作確認

Measure-Commanddocker pull の時間を計ってみる。

docker image rmi hello-world
docker image prune

Measure-Command {docker pull hello-world}
# => TotalSeconds      : 5.4094275

docker image rmi hello-world
docker image prune

Measure-Command {docker pull hello-world}
# => TotalSeconds      : 2.0318131

docker compose logs にも、ミスキャッシュしてからヒットしたというログが残っている。

> docker compose logs
...(略)
tmp-docker-registry-proxy-1  | {"access_time":"02/Oct/2022:18:46:34 +0000","upstream_cache_status":"MISS","method":"HEAD
","uri":"/v2/library/hello-world/manifests/latest","request_type":"manifest-default","status":"200","bytes_sent":"0","up
stream_response_time":"0.720","host":"registry-1.docker.io","proxy_host":"registry-1.docker.io","upstream":"34.205.13.15
4:443"}
...(略)
tmp-docker-registry-proxy-1  | {"access_time":"02/Oct/2022:18:47:20 +0000","upstream_cache_status":"HIT","method":"HEAD"
,"uri":"/v2/library/hello-world/manifests/latest","request_type":"manifest-default","status":"200","bytes_sent":"0","ups
tream_response_time":"","host":"registry-1.docker.io","proxy_host":"registry-1.docker.io","upstream":""}
...(略)

キャッシュディレクトリにデータも入っている。

> docker compose exec docker-registry-proxy find /docker_mirror_cache
/docker_mirror_cache
/docker_mirror_cache/a
/docker_mirror_cache/a/47
/docker_mirror_cache/a/47/d0862d346f039b9a238728e97237d47a
/docker_mirror_cache/7
/docker_mirror_cache/7/c4
/docker_mirror_cache/7/c4/d2c014ee5630f39c4a0fb8a1ce8d5c47
/docker_mirror_cache/5
/docker_mirror_cache/5/cf
/docker_mirror_cache/5/cf/e44914286ca296d3a45dc06185d03cf5
/docker_mirror_cache/d
/docker_mirror_cache/d/36
/docker_mirror_cache/d/36/7a4ad43a77fb3fc1a5cb477b7e2f136d
/docker_mirror_cache/c
/docker_mirror_cache/c/71
/docker_mirror_cache/c/71/27629938b7c2102ec0b9185900e4871c

良さそう、以上。

Windows 以外でのプロキシ設定方法

systemd でマシンごとに設定する方法と、 ~/.docker/config.json でユーザーごとに設定する方法がある。

systemd でマシンごとに設定する方法

systemd の docker.service 向けの設定ファイルを作成し、その中で環境変数を渡す。

docker.service 用の設定ファイル格納ディレクトリを作成

sudo mkdir /etc/systemd/system/docker.service.d

作成したディレクトリ内に設定ファイルを作成

今回は http-proxy.conf という名前で作成。

[Service]
Environment=HTTP_PROXY=http://192.168.2.101:3128/
Environment=HTTPS_PROXY=http://192.168.2.101:3128/

Docker サービスリスタート

sudo systemctl daemon-reload
sudo systemctl restart docker.service

~/.docker/config.json でユーザーごとに設定する方法

~/.docker/config.json を作成し、以下のように設定する。

{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://192.168.1.12:3128",
     "httpsProxy": "http://192.168.1.12:3128",
     "noProxy": "*.test.example.com,.example2.com,127.0.0.0/8"
   }
 }
}

参考資料

0 件のコメント:

コメントを投稿