Google Cloud Platform

Container Registry 用に独自のカスタム ドメインを作り上げる

#containers

※この投稿は米国時間 2020 年 11 月 6 日に、Google Cloud blog に投稿されたものの抄訳です。

Container RegistryArtifact Registry から公開コンテナ イメージを提供する場合、コンテナ イメージをダウンロードするユーザーにプロジェクト ID とその他の詳細を公開することになります。しかし、小さなミドルウェアを作成してサーバーレスで実行すれば、レジストリの動作をカスタマイズできます。

この記事では、サーバーレス リバース プロキシを開発して実行し、gcr.io ではなくカスタム ドメイン名でイメージを公開するなど、レジストリの動作をカスタマイズする方法をご紹介します。

「docker pull」の詳細

コンテナ レジストリからコンテナ イメージを提供できるのは不思議ではありません。Google Container Registry、Google Artifact Registry、Docker Hub などのすべてのコンテナ イメージ レジストリが、Open API 仕様を実装しているためです。

したがって、docker pull gcr.io/google-samples/hello:1.0 などの pull コマンドを実際に実行すると、基盤となるコンテナ エンジン(Docker エンジンなど)で https://gcr.io/v2/google-samples/hello-app/manifests/1.0 をはじめとする REST エンドポイントに対して一連の HTTP RESTAPI 呼び出しを行い、コンテナ イメージの詳細を確認し、レイヤ blob をダウンロードすることができます。crane などのツールを使用して、イメージの pull や push を試行した場合、コンテナ レジストリの動作をさらに調べられます。

コンテナ レジストリ向けのカスタム ドメイン

カスタム ドメインでイメージを提供することは、オープンソース プロジェクトなどの公開イメージに特に役立ちます。また、基盤となるレジストリ(gcr.io/* など)の詳細をユーザーから隠す場合にも有効です。

Container Registry や Artifact Registry などのレジストリを使用してイメージを公開すると、プロジェクト ID が外部に公開されるだけでなく、次のようにイメージ名が非常に長くなってしまう可能性があります。

docker pull us-central1-docker.pkg.dev/<project-id>/<registry-name>/<image-name>

上記の例から、コンテナ イメージの名前によって、レジストリがホストされる場所、ひいては API 呼び出しが実行されるホストが決まることがわかります。カスタム ドメイン(example.com など)でイメージを提供するレジストリを作成する場合、コンテナ イメージ参照として example.com/IMAGE:TAG を指定することで、イメージを pull できます。次に、API リクエストがプロキシ経由で実際のレジストリ ホストに送信されます。

こうした処理を行うために、既存の Google Container Registry や Artifact Registry を使用してイメージを保存し、イメージ上に「リバース プロキシ」を構築するだけで、独自のカスタム ドメイン名でトラフィックを処理しながら受信リクエストを転送できます。

Severless Proxy

Cloud Run: ジョブに適したツール

Cloud Run は、このようなアプリケーションを Google Cloud でホストするのにうってつけです。Cloud Run はサーバーレス コンテナ ホスティング プラットフォームであり、提供された各リクエストに対してのみ料金が発生するため、ここで料金設定は特に重要です。

この設計では、リクエストが処理されている間(誰かがイメージを pull している間)にのみ課金されるため、無料枠に収まりやすくなります。

このプロキシを Google Container Registry で使用する場合、実際のイメージレイヤ(blob)はレジストリ API からダウンロードされません(代わりに、レイヤ tarball を pull するために Cloud Storage ダウンロード リンクが生成されます)。ギガバイト規模の可能性がある大規模なレイヤはこのプロキシを通過しないため、Cloud Run の費用を低く抑えるのは簡単です。

ただし、Artifact Registry で使用する場合、イメージのレイヤ blob はこのプロキシを経由して提供されるため、より大きな blob に対応する下り(外向き)ネットワーク料金が発生し、リクエスト時に大量のレスポンスをプロキシする結果として Cloud Run で「請求対象時間」が長くなることで、費用が高くなります。

レジストリのリバース プロキシを構築する

このタスクを実行するために、Go プログラミング言語で 200 行ほどのコードを書き、単純なリバース プロキシを構築しました。このプロキシは httputil.ReverseProxy を使用し、認証情報ネゴシエーションに関する特別な処理を追加して、公開イメージ(および必要に応じて公的なプライベート イメージ)を提供します。

サンプルコードとデプロイ手順は、私のリポジトリ github.com/ahmetb/serverless-registry-proxy にあります。このプロキシをプロジェクトにデプロイしてカスタム ドメインで公開イメージを提供するには、リポジトリにある詳細な手順をご参照ください。大まかには次のことを行う必要があります。

1.リバース プロキシ アプリをソースコードからコンテナ イメージにビルドし、レジストリに push します。

2.Google Container Registry や Artifact Registry に Docker レジストリを作成し、認証情報なしでイメージを提供できるように一般公開します。

3.リバース プロキシでリクエストをプロキシするレジストリを指定しながら、リバース プロキシを一般公開の Cloud Run サービスとしてデプロイします。

4.Cloud Console で、この Cloud Run サービスにドメイン名をマッピングします。

5.Cloud Run でカスタム ドメインの SSL 証明書が作成、構成されます。

6.DNS レコードの伝播が完了すれば準備 OK です。これで、ユーザーは docker pull <YOUR-DOMAIN>/<IMAGE>:<TAG> を実行して、カスタム ドメインからイメージをダウンロードできるようになりました。

まとめ

コンテナ レジストリの前に「ミドルウェア プロキシ」を構築し、Cloud Run などのサーバーレス プラットフォームで費用を最小限に抑えて手軽にホストするという考え方を広げられます。

たとえば、特定のイメージや特定のタグのみを提供するレジストリ プロキシを構築できます。同様に、既存のレジストリの上に独自の認証レイヤを構築できます。Registry API は標準であるため、私のサンプルコードは Docker Hub などの他のコンテナ レジストリでも動作します。このようにすると、Docker Hub やその他のレジストリからイメージを提供するサーバーレス プロキシを Cloud Run でホストできます。

ソースコードを確認し、必要に応じてプロジェクトをフォークし拡張していただいてかまいません。このサンプルのオープンソース プロジェクトが、カスタム ドメインでコンテナ レジストリを提供する際にも役立てば幸いです。

-シニア デベロッパー アドボケイト Ahmet Alp Balkan