Dockerfiles と Buildpacks を理解するための 7 つの画像、この 2 つをどのように選択すればよいでしょうか?

Dockerfiles と Buildpacks を理解するための 7 つの画像、この 2 つをどのように選択すればよいでしょうか?

スクリプト化された Dockerfile と比較して、宣言型のクラウドネイティブ ビルドパックはいくつかの新しいシナリオをサポートします。

コンテナはどこにでもある

コンテナはほとんどのソフトウェア配信パイプラインに遍在しており、直接目に見えない場合もありますが、舞台裏で存在しています。 Kubernetes、通常の Docker ホスト、サーバーレス関数、または他の多くのオーケストレーション プラットフォームでソフトウェアを実行する場合でも、コンテナーは不変で実行可能なソフトウェア成果物を表します。

アプリケーションのソース コードを実行中のアプリケーションに変換するには、中間のコンテナー ビルド ステージが必要であり、ソフトウェアをコンテナーに変換する非常に一般的な方法は Dockerfile を使用することです。

Dockerファイル

Dockerfile からコンテナを構築するのはスクリプト化されたアプローチであり、Dockerfile に含まれる内容のほとんどは、基本的にソフトウェアの構築や依存関係のインストールなどに必要なコマンドです。これは、Dockerfile の使用方法を学習するための学習曲線が緩やかであり、既存のビルド スクリプトをそれほど労力をかけずに Dockerfile に移植できることも意味します。

しかし、高品質のコンテナイメージを作成するのは簡単ではないことがわかりました。インターネットには、小さくて安全なベストプラクティスイメージを作成するためのガイドが満載です。通常、次の点を中心に展開します。

  • SIGTERM などのシグナルが適切に処理されることを保証することは、コンテナ契約の一部です。
  • アプリケーションを root ユーザーとして実行しないでください。
  • コンテナには不要なツール、シークレット、ビルド成果物を含めないでください。
  • 最も変更が少ないレイヤーを最初など、キャッシュを最適化する順序でレイヤーを追加します。
  • 画像に適切なタグと署名を付けます。

以下は、NodeJS アプリケーションに対してこれらの推奨事項の一部を実装する Dockerfile を示しています。 2 段階のビルドを使用して小さなイメージを作成し、非ルートとして実行し、操作を慎重に順序付けてキャッシュを改善します。

 ノードから: 16.13 .1 - alpine3 .14 AS ビルダー
WORKDIR / usr / src / app
パッケージ* .json ./ をコピーします
npm ci を実行します
tsconfig.json をコピーします
コピーsrc src
実行npm run build
npm prune を実行 本番環境
送信元ノード: 16.13 .1 - alpine3 .14
WORKDIR / usr / src / app
ユーザーノード
ENV NODE_ENV プロダクション
コピー from = builder /usr/src/app/node_modules/./node_modules
コピー from = builder /usr/src/app/dist/./dist
エクスポーズ8000
コマンド[ "node" , "/usr/src/app/dist/main.js" ]

高品質の Dockerfile を作成するにはかなりの労力が必要であり、場合によっては Dockerfile が別のプロジェクトの Dockerfile の単なるコピーになることもあります。これにより Dockerfile が断片化され、複数のコンテナを持つ組織ではすぐに管理不能になる可能性があります。

ビルドパック

ビルドパックは、特定のタイプのほとんどのアプリケーションでは、アプリケーションのソース コードをコンテナーに変換することはほぼ同じであるという考えから生まれました。つまり、このプロセス用に再利用可能なプログラムを設計できるということです。このコンセプトは、Heroku によって開始され、Cloud Foundry、Google App engine、Gitlab、CircleCI などに採用されて以来、10 年以上にわたって開発されてきました。

コミュニティは、セキュリティとベストプラクティスのレベルが異なる各アプリケーションに対して断片化された Dockerfile を使用するのではなく、高品質のコンテナ イメージ ビルドを提供できるように懸命に取り組んでいます。

コンテナイメージを構築するための宣言的なアプローチ

ビルドパックを使用する場合は、ビルドパックがコンテナを構築する方法を理解する必要があります。 Dockerfile を使用してコンテナを構築する方法をスクリプト化するのではなく、コンテナにパッケージ化するものを宣言し、ビルドパックに詳細を判断させることができます。

ビルドパックはいくつかのフェーズを実装しますが、そのうちの 2 つは次のとおりです。

  • 検出: 各ビルドパックは、コンテナ ビルドに参加できるかどうかを検出します。たとえば、NodeJS アプリケーションの場合、_npm_ ビルドパックは package.json ファイルを探すことがあります。見つかった場合、ビルドパックはビルドに参加して依存関係を提供できることをビルダーに通知します。 Python ビルドパックは requirements.txt ファイルを検索しますが、NodeJS アプリケーションでは見つからないため、ビルドには参加しません。
  • ビルド: このフェーズでは、ビルドに参加できることを示しているすべてのビルドパックが実行され、ビルドが達成されます。上で述べたように、ビルドパックが何をビルドすべきかを検出する方法を知ることが重要です。つまり、NodeJS アプリケーションの開発者は、プロジェクトに package.json ファイルが含まれていることを確認する必要があります。さらに、特定のバージョンの Node ランタイムやその他の依存関係が必要な場合は、package.json ファイルでそれを明確にする必要があります。次に例を示します。
 {
「エンジン」 :{
「ノード」 : 「16.13.1」
"npm" : "8.1.2"
},
「依存関係」 : {
「エクスプレス」「4.17.2」
}
...
}

コンテナ イメージはさまざまな形式でメタデータを保持し、ビルドパックは多くの場合、環境変数を使用してメタデータ設定を宣言します。以下は、Paketo image-labels ビルドパックを使用して、環境変数を使用してコンテナ イメージに標準の org.opencontainers.description ラベルを設定する例です。環境変数の設定は、ビルド設定を宣言するための一般的な形式である project.toml ファイルを介して行われます。

 [[ 建てる環境]]
名前= "BP_OCI_DESCRIPTION"
value = "https://github.com/MichaelVL/buildpacks からのサンプル NodeJS"

Buildpacks のこの宣言型 API を理解することは、開発者にとって不可欠です。開発者は Dockerfiles を気にする必要はなく、ビルドパックの宣言型 API を知っておく必要があります。

再現可能なビルド、安全な配信チェーン

ビルドパックは、再現可能なビルドを実現することを目指しています。ビルド プロセスは完全に決定論的であり、同じ入力で実行すると同じ出力が生成されます。これにより、どのアプリケーション バイナリまたはソースがコンテナーにパッケージ化されているかを正確に検証し、悪意のあるアプリケーションがコンテナーにパッケージ化されるのからソフトウェア配信チェーンを保護することができます。

Dockerfiles を使用してイメージを構築する場合、まったく同じ入力が提供された場合でも、コンテナ イメージ (およびそのハッシュ sha256 ダイジェスト) はイメージが再構築されるたびに変更されます。

再現可能なビルドはソフトウェア アーティファクト サプライ チェーン レベル 4 の要件であり、ビルドパックはコンテナー イメージ サプライ チェーンのセキュリティを向上させる重要なツールです。

再現可能なビルドは、コンテナ レイヤーの不要な再構築を回避するための効果的なメカニズムでもあります。

再構築速度とキャッシュの改善

Dockerfile 内の各行は、基本的に最終的なコンテナ イメージにレイヤーを追加します。前のレイヤーが変更されない限り、レイヤーはキャッシュされ、再利用されます。先行するレイヤーが変更されると、Docker は再現可能なビルドを適用しないため、後続のすべてのレイヤーが再構築され、変更されます。

ビルドパックでは、各ビルドパックがコンテナ イメージにレイヤーを提供します。ビルドパックの入力が変更されない場合、前のレイヤーが変更されたかどうかに関係なく、ビルドパックのレイヤーは変更されません。さらに、ビルドパックを使用すると、他のビルドパックによって生成されたレイヤーに影響を与えずに、個々のレイヤーを置き換えることができます。

コンテナ ベース イメージを更新する必要がある場合 (たとえば、セキュリティ上の問題のため)、他のアプリケーション レイヤーを再構築せずに、コンテナ イメージにそのレイヤーを再インストールできます。 Dockerfile ベースのワークフローを使用してこれを実現するのは困難です。

シングルレイヤー リベースは、コンテナ イメージのビルド時間だけでなく、コンテナのデプロイメントにも大きな改善をもたらします。特定のベースイメージを使用する 10 個のサービスがあると想像してください。セキュリティ上の問題によりこのベースイメージを更新する必要がある場合、Dockerfile に対してビルドを行うと、すべてのイメージのすべてのレイヤーが再構築されます。これにはビルド時間がかかり、10 個の新しいイメージ全体がダウンロードされます。ビルドパックのリベース メソッドを使用する場合、新しい共有ベース イメージを取得するだけで済みます。

コンテナは42年も経っているんですか?

ビルドパックを使用してコンテナをビルドすると、予期しないタイムスタンプが発生します。

 $ docker イメージls
リポジトリタグイメージID 作成サイズ
サンプル- アプリ最新4713 a8f7d9bb 42 202 MB

これは再現可能なビルドの副作用です。再現可能なビルドを実現するために、コンテナ イメージの違いを引き起こす時間依存データを回避すべく、時間が固定されます。ビルドパックは、古いファイル形式との互換性のために選択された、タイムスタンプの起点が 1980 00:00:01 であるイメージをビルドします。

ビルドパックを使用する際の役割

ビルドパックを使用してコンテナを構築する場合、次の 2 つの役割があります。

  • アプリケーション開発者: 開発者の焦点はアプリケーション中心である必要があり、コンテナ ビルドに関連する主な責任は、アプリケーション ソース、依存関係のバージョン (NodeJS アプリケーションの場合は package.json など)、およびアプリケーション名やバージョンなどのメタデータを提供することです。コンテナの構築については、組織がキュレートしたビルダー/ビルドパックに完全な制御を委任します。ほとんどの問題をプラットフォーム オペレーターに委任するには、開発者はビルダーのバージョンを修正するのではなく、最新のビルダー/ビルドパックを使用する必要があります。
  • ビルド プラットフォーム オペレーター: ビルド プラットフォーム オペレーターの責任は、開発者がコンテナのビルドに適用できる、厳選されたビルダーとビルドパックのセットを提供することです。これは主に、Paketo ビルドパックなどのコミュニティ ビルダーを活用することですが、オペレーターは企業固有の目的のために、独自に設計したビルドパックを追加することもできます。たとえば、会社に関連するメタデータを追加することが考えられます。ビルド プラットフォーム オペレーターの主な懸念事項は、コンテナー ランタイム イメージ (コンテナー ベース イメージ) の更新とセキュリティです。

この関心の分離は、プラットフォーム ビルド オペレーターがコンテナ イメージを制御できるため、複数のコンテナ イメージを管理する組織にとって非常に価値があります。たとえば、実行中のイメージでセキュリティ上の問題が発見された場合、ビルダーの実行イメージを変更することで、新しい実行中のイメージを使用してすべてのコンテナを再構築できます。上で述べたように、これは非常に効率的なレイヤーのリベースになります。 Dockerfile を使用すると、すべてのアプリケーション Dockerfile のベースイメージを更新する必要があり、すべてのコンテナ イメージ レイヤーの再構築がトリガーされます。

コンテナにはどのようなソフトウェア部品表が含まれていますか

ビルドパックが Dockerfile ビルド プロセスを強化する方法の 1 つの例は、ビルド関連のメタデータをコンテナー イメージに添付する方法です。ソフトウェア プロジェクトには多くの依存関係が含まれており、これらの依存関係に関する情報はイメージのビルド時にコンテナー イメージに埋め込まれます。

ソフトウェア部品表 (SBOM) は、コンテナ イメージに含まれるコンポーネントの構造化されたリストです。これを使用すると、SBOM を既知のセキュリティ問題と比較することで、安全なソフトウェアのみが使用されていることを確認できます。 SBOM は、どのソフトウェア ライセンスがソフトウェアを管理しているかなどを確認するためにも使用できます。CycloneDX と SPDX は、構造化された SBOM データの 2 つの一般的な標準です。

以下は、NodeJS プロジェクトの SBOM からの抜粋です。ここでは、使用されている Node エンジンの正確なバージョンと、それを提供するビルドパックを確認できます。

 {
{
"name" : "ノードエンジン" ,
「メタデータ」 : {
"ソース" : {
「チェックサム」 : {
「ハッシュ」 : 「34b23965457fb0587cda6fa898e5d030211f5f374cb6」
},
"uri" : "https://nodejs.org/.../node-v16.13.1.tar.gz"
},
「バージョン」 : 「16.13.1」
},
「ビルドパック」 : {
"id" : "paketo-buildpacks/node-engine" ,
「バージョン」 : 「0.11.2」
}
}
}

SBOM を使用してソフトウェアを保護することは、コンテナ イメージ スキャナーの使用を強力に補完します。 SBOM はビルドパックから作成されるため、配信チェーンを正確かつ明確に識別します。コンテナ イメージ スキャナーは、コンテナの実際のコンテンツからこのバージョンを差し引く必要があるため、精度は低くなります。

Buildpacks の使い方は?

Cloud Native Buildpacks では、ビルド プロセスと Buildpacks が、ビルダー イメージとランナー イメージの 2 つのコンテナー イメージに含まれています。ある意味、これは改良された Dockerfile の 2 段階ビルドと見ることができます。次の図は、2 段階の Dockerfile ビルドが Buildpacks にどのようにマッピングされるかを示しています。 NodeJS アプリケーションのビルド ロジックがビルドパックにどのようにマッピングされるかに注目してください (通常、このようなアプリケーション ビルドは複数のビルドパックに分散されます)

ビルダー イメージには、順序付けられた一連のビルドパックを使用してビルドを行うためのロジック、ビルドパックのライフサイクル コンポーネントのオーケストレーター、および実行中のイメージへの参照が含まれています。 Dockerfile は線形に処理されるため、Dockerfile とライフサイクル コンポーネントの間には並列処理はありません。検出フェーズでは、ビルドパックはビルドをオプトインまたはオプトアウトし、ライフサイクル コンポーネントがこれを管理します。

最後に、ライフサイクル コンポーネントをトリガーするためのツールが必要です。これは、docker build コマンドに非常に似ています。これにはさまざまなツールがあり、最もよく知られているのは pack と Tekton ですが、CircleCI や Gitlab などの商用継続的インテグレーション ベンダーもビルドパックを使用したビルドをサポートしています。

pack を使用した Github アクション ワークフローの例については、こちらをご覧ください。

結論は

経験豊富な Dockerfile 作成者は、Dockerfile からビルドパックに移行するときに詳細を制御できなくなると感じるかもしれませんが、上記の利点により、ビルドパックの使用にオープンな心で取り組むことができるようになることが期待されます。ほとんどの開発者はビルドパックを気に入ると思います。コンテナの構築と Dockerfile の保守は主な焦点ではなく、むしろアプリケーションのデプロイに必要な手順でした。ビルド プラットフォーム オペレーター、SRE、セキュリティ チームにとって、ビルドパックはコンテナ イメージとコンテナ イメージに組み込まれた成果物に対する制御を復元するため、非常に便利です。

Dockerfile をクラウドネイティブ ビルドパックに置き換えると、コンテナ イメージの構築方法が変わります。

開発者や組織にとって、宣言部分に重点を置くことが重要です。コンテナをどのように構築するか、また何を構築するかを宣言する方法を学ぶことが最も重要になります。

ビルドパックは完璧ですか?

そうでもないです。この記事を書いている間、冒頭で提案した 2 段階 Dockerfile のリーン コンテナー ビルドを再現しようとしましたが、完全には実現できず (Paketo ビルダーを使用)、結果として得られるコンテナーのサイズが少し大きくなってしまいました。ただし、ビルドパックは将来改善されることを期待しています。

ビルドパックを使用してコンテナにパッケージ化するのが難しいアプリケーションもいくつかあります。たとえば、コンテナ (VM スタイルのコンテナ) にパッケージ化された従来のモノリシック アプリケーションは、カスタム ビルドパックなしでは実装が困難です。このようなアプリケーションはビルドパックとうまく連携せず、Dockerfile の低レベルの制御が必要になる可能性があります。これはおそらく、コンテナ パッケージングで認識しておくべきことです。

<<:  K8S ステートレスおよびステートフル、初心者向けガイド!

>>:  夏休み中にオープンソースを学んで賞品を獲得しましょう。 2022 Red Hat ITプロフェッショナル総合スキルコンテストにぜひご参加ください

推薦する

クラウド ストレージ製品の簡単な分析

主なクラウド ストレージ製品には、オブジェクト ストレージ、ブロック ストレージ、ネットワーク ファ...

誰でも使えるアジャイルメトリクスツール! Kyligence ZenがGAバージョンを正式にリリース

4月11日、Kyligence Indicator Platform製品発表会が盛況のうちに開催され...

readydedis: 月額 6 ドル、米国での無制限トラフィック VPS、1G メモリ/1 コア (ryzen9 3950X)/25g NVMe/1Gbps 帯域幅

トラフィックを流したい人は、トラフィックが無制限の VPS が必要な場合もあります。readyded...

weloveservers - 1g メモリ/60g ハードディスク/1T トラフィック/4 データセンター/年間 25 ドル

weloveserversは、ドイツのフランクフルトに新しいデータセンター(グローバルスイッチデータ...

ガートナー、10年後のクラウドコンピューティング市場を予測:AWS、Alibaba Cloud、その他のベンダー

クラウド コンピューティング、特にクラウド内の仮想化コンピューティング リソースの提供 (IaaS ...

データセンター分散スケジューリングのスーパーマン: DCOS - 急成長するデータ都市へご案内

DCOS は、データセンター全体に分散スケジューリングおよび調整機能を提供し、データセンター レベル...

Sharktech データセンター: 159 ドル/2*E5-2670 販売中 | 10Gbps 無制限データ

15 年の歴史を持つ高防御サーバー販売業者 Sharktech (Shark Data Center...

個人SEOの依頼を受ける際は、誇張せず現実的に

著者は3年間SEOに携わっています。最初の2年間は主に自分のサイトを最適化していました。1つは実践し...

bandwagonhost-再び半額/Gポート

クーポンコード: WHT24H、VPS を半額で購入、12 時間有効。 Bandwagonhost ...

ウェブサイトがキーワードを積み重ねることで検索エンジンからのペナルティを回避する理由の分析

いわゆるキーワードスタッフィングとは、ウェブページの記述規則によれば、前後の文脈と明らかに矛盾する、...

百度の調整は将来の検索エンジン開発の傾向を明らかにする

百度は6月22日から大規模な調整を行っており、6月末まで続いた。最も大きな変化は28日に起きた。当初...

百度はソーシャル検索に注目し始めており、SEOに影響を与える可能性がある

Admin5 Webmaster Networkは2月29日、昨日、百度開放型ブランドゾーンがプロモ...

一部の淡黄色のアプリケーションは失敗するのに、他のアプリケーションはリストされるのはなぜですか?

【夜の読書】快博秘境が次々とトラブルに。当初は「突然閉鎖されたウェブサイトは人々の間で最も人気がある...

「MQ シリーズをマスターする」 - Kafka ストレージ選択の秘密

[[405722]]みなさんこんにちは。私はウー兄弟です。これは、Kafka に関する「Master...

Yibaixun Technologyは「職人精神」を活用して、さまざまな業界の顧客のWebサイト構築を支援します

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています現在、イン...