Jib を使用して Docker イメージを構築すると、リモートの Docker リポジトリ ストレージを最適化できますか?
はい。確かに、画像レイヤーの再現性が高いため、これはかなりの程度に役立ちます。を使用するだけDockerfile
では、通常、ほとんどのレイヤーの再現性が完全に失われます。これは、ファイルのタイムスタンプがレイヤーが同一であるかどうかのチェックに組み込まれるためです。たとえば、ファイルのバイト.class
がまったく変更されていない場合でも、ファイルを再生成すると、再現性が失われます。これは jar ではさらに悪いことです。タイムスタンプが変更される可能性があるだけでなく、jar メタデータ (たとえばMETA-INF/MANIFEST.MF
、
これにより、実際にはコードがほとんど変更されていない場合でも、ビルドするたびに大きな (250 MB) 新しいイメージが作成されます。これは、fat jar に共有依存関係 (頻繁に変更されない) とコードの両方が含まれているためです。
サイズが大きい (250MB) ことは部分的に修正しますが、jar が大きいためではありません。ビルドされたイメージのサイズは、それがファット jar ではなく、共有ライブラリ用に別のレイヤーを指定した場合でも、常に 250MB になります。gcr.io/distroless/java:11
最終的なイメージのサイズ (250MB) には、イメージがどのツールでどのように構築されたかに関係なく、基本イメージのサイズ ( ) と共有ライブラリのサイズが常に含まれます。
ただし、Docker エンジンは、ストレージ内で既に認識しているレイヤーを複製しません。同様に、リモート レジストリは、リポジトリに既に存在するレイヤーを複製することもありません。さらに、多くの場合、レジストリは異なるリポジトリ間でレイヤーのコピーを 1 つだけ保存することさえあります。したがって、コード (つまり jar) のみを更新すると、その jar を含むレイヤーのみが新しいストレージ スペースを占有します。また、Docker と Jib は、新しいレイヤーのみをネットワーク経由でリモート レジストリに送信します。つまり、 のベース イメージ レイヤーはgcr.io/distroless/java:11
送信されません。
/opt/libs に依存関係のみを含む基本イメージを作成し、それを呼び出してspring-base:1.0.0
、プライベート Docker レジストリにプッシュしましょう。
共有ライブラリを含めるためだけに別のイメージを作成することは、前例のないことではなく、これを試みている人を見てきました。ただし、この特別な基本イメージを、組織内のさまざまな種類のイメージ間で共有するための独立したスタンドアロン イメージとして概念的に扱うつもりはないと思います。したがって、この状況でそうするのは型にはまらないと思います。ストレージスペース(およびネットワーク帯域幅)の節約に関して頭の中で思い浮かんだだけの場合、このトリックはおそらく不要です。読み続けてください。
これらの画像ははるかに小さいことが予想されます
いいえ。説明したとおり、何があっても同じサイズの 250MB のイメージを作成します。これには、共有ライブラリを含む基本イメージのサイズが含まれます。を実行するdocker images
と、ローカルの Docker エンジンはイメージ サイズが 250MB であることを示します。しかし、私が言ったように、新しいイメージを構築するたびに、Docker エンジンが追加の 250 MB のスペースを占有するという意味ではありません。
依存関係のある大きな基本イメージは一度だけ保存されます
はい。ただし、これは、最初からFROM gcr.io/distroless/java:11
. 共有ライブラリ用に独自の別のレイヤーを作成し、そのレイヤーを安定した (つまり、再現可能な) 状態に保つことができる限り、共有ライブラリを別の「ベース イメージ」に押し込むことは無意味です。そして、ジブはそのようなレイヤーを再現可能に構築することに非常に長けています。レジストリに保存されるビットの粒度はイメージではなくレイヤーであるため、ライブラリ レイヤーが何らかの「ベース イメージ」にあることを「マーク」する必要はありません (ライブラリ用に独自のレイヤーを作成する限り)。レジストリはレイヤーのみを認識し、「このイメージはレイヤー A、レイヤー B、レイヤー C とこのメタデータで構成される」と宣言するだけで「イメージ」の概念が形成されます。イメージにはベース イメージの概念さえありません。「この画像は、このベース画像の上にレイヤーAを置いたものです」とは言いません。
多くのストレージを節約します。
したがって、これは真実ではありません。結局のところ、Docker エンジンとレジストリは、正当な理由もなく同じレイヤーを複数回保存することはありません。
私たちはそれを統合して使用./gradlew jibDockerBuild
し、依存関係、リソース、およびクラスのレイヤーを作成しているように見えますが、まだ 1 つの大きなイメージしかありません。
はい。画像サイズは250MBになります。Dockerfile
これは、またはその他のイメージ構築ツールを使用する場合にも当てはまります。ただし、Jib を使用する場合、アプリケーション.java
ファイルのみを変更すると、再構築時に、Jib はネットワーク経由で小さなアプリケーション層 (共有ライブラリやリソースを含まない) のみをリモート レジストリに送信します。ジブは再現性が高いため、250MB のレイヤー全体を送信するわけではありません。同様に、共有ライブラリのみを更新する場合、Jib はライブラリ レイヤーのみを送信し、時間、帯域幅、およびストレージを節約します。
ただし、Docker エンジン API の機能が限られているため、Jib が特定のレイヤーが既に Docker エンジンに格納されているかどうかを確認する方法がないため、Jib は使用時に 250MB のレイヤー全体をロードする必要があります。jibDockerBuild
. 読み込みはネットワークを経由せずにローカルで行われるため、これは通常は問題になりません。しかし、この API の制限により、驚くべきことに、Jib がイメージをリモート レジストリに直接プッシュする方が、ローカルの Docker エンジンにプッシュするよりも高速であることがよくあります。ジブは、変更されたレイヤーのみを送信する必要があります。ただし、何度も強調してきたように、Jib (または他のイメージ構築ツール) が 250MB のレイヤー全体を Docker エンジンにロードしたとしても、エンジンは必要なもの (つまり、見たことのない新しいレイヤー) のみを保存します。またはそう信じている)。ベース イメージまたは共有ライブラリ レイヤーは複製されません。新しい、異なるレイヤーのみがストレージを占有します。ではDockerfile
、再現性が低いために実際には新しいレイヤーではありませんが、通常は「新しいレイヤー」を生成することになります。