色々実験していると、各種 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 の設定
プロキシ設定
- タスクトレイの 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-Command
で docker 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"
}
}
}
参考資料
- rpardini/docker-registry-proxy: An HTTPS Proxy for Docker providing centralized configuration and caching of any registry (quay.io, DockerHub, k8s.gcr.io)
- コンテナレジストリの可用性を高める取り組み - Cybozu Inside Out | サイボウズエンジニアのブログ
- プロキシサーバを使うように Docker を設定 — Docker-docs-ja 20.10 ドキュメント
- プロキシのある環境でDockerを動かす方法 - Qiita
- systemd で Docker の制御 — Docker-docs-ja 20.10 ドキュメント
- Import-Certificate (pki) | Microsoft Learn