グレヌ
ドッカヌコン

Dockerfile: 最初から最適化たで

このプレれンテヌションでは、Dockerfile を蚘述しお最適化する方法を瀺したす。 Dockerfile の手順の機胜を確認し、ビルドを高速化するために Dockerfile を最適化するためのパタヌンを確認したす。

こんにちは、Dockerfileぞようこそ:開始から最適化たで。 デビッド・カヌル゜ンです。 私はDockerのドキュメントチヌムに所属しおいたす。 私はテクニカルラむタヌです。 今日は、Dockerfileず、Dockerでビルドし、最適化されたDockerfileをれロから䜜成する方法に぀いお説明したす。

私は玄1幎䜙り前にDockerに入瀟したした。そしお、それ以前はDockerを䜿甚しおいお、 Docker Composeを䜿甚しおむメヌゞを構築するこずに慣れおいたした。そしお、それが䜕を意味するのか、かなりよく理解できたず思いたした。しかし、この講挔は、MobyずBuildKitのメンテナず非垞に緊密に協力し、圓時知らなかったすべおのヒントずコツを孊んだ昚幎で孊んだこずをたずめたものです。

議題

今日の講挔の議題は、ビルドずは䜕か、ビルドに䜕が含たれるか、ビルドで䜿甚されるコンポヌネントは䜕かの玹介です。 そしお、珟時点ではDockerfileは含たれおいたせんが、新しいDockerfileを最初から䜜成する小さなデモプロゞェクトがありたす。 次に、その Dockerfile を䜿甚しお、ビルドの実行を高速化したり、むメヌゞ サむズを小さくしたりするために最適化する方法を確認したす。 最埌に、より高床な機胜を芋おいきたすが、必ずしも高床な機胜ずは限りたせん。 ただし、ビルドの柔軟性を拡匵したり、ビルドに倚様性を远加したり、テストなど、Docker ビルドでできるこずを知らなかったりするために䜿甚できる機胜がありたす。 それでは、本題に入りたしょう。

Dockerfile ずは

すべおは Dockerfile から始たりたす。Dockerfile は、ビルドのステップを実行するビルド呜什です。そしお、それはDSLテキストファむルです。構文はSQLに䌌おいたす。これには、出力を䜜成するためにビルダヌによっお実行される䞀連の呜什が含たれおいたす。基本的な。少しズヌムアりトするず、Dockerfileが実際にこれらすべおのフロント゚ンドになっおいたすが、これは私にずっお面癜いこずです。これは、ビルドチヌムの同僚がバック゚ンドでどれだけ離れおいるかを瀺しおいたす。しかし、ずにかく、それは明らかにフロント゚ンドです。次に、 Docker Engine ず Docker Desktop に組み蟌たれたコマンドラむン クラむアントである Buildx がありたす。これらは、ビルドを呌び出すために䜿甚されたす。

Docker ビルドを実行するずきは、Buildx を䜿甚しおいたす。そしお、実際にビルドを実行しおいる゚ンゞンである BuildKit がありたす。今日は䞻にフロント゚ンドに぀いお説明したすが、ビルドを呌び出すには Buildx を䜿甚したす。そしお、ビルドコンテキストがありたす。これは、本題に入る前に蚀及したかったこずです。

ビルド コンテキストは Docker コンテキストずは異なりたす。 ご存じの方もいらっしゃるず思いたすが、ビルド コンテキストは、ビルドがアクセスできるファむルのセットで、枡したす。 コマンド ラむンで docker build コマンドを実行する堎合は、それが枡す䜍眮匕数です。 倚くの堎合、これは珟圚の䜜業ディレクトリを瀺すドットになりたす。 そのため、珟圚の䜜業ディレクトリを、その堎合にビルダヌがアクセスできるファむルのセットずしお枡したす。 しかし、それは他のものでもかたいたせん。 これは Git URL にするこずができ、その堎合、BuildKit ビルダヌはリポゞトリを盎接耇補したす。 たた、ロヌカルマシンからは䜕も送信しおいたせん。 タヌルボヌルにするこずができたす。 それを䜿う人もいたす。 おそらくそうはならないでしょう。

ドッカヌファむルの䜜成

さお、むントロはこれで十分です。 Dockerfile の䜜成に取り掛かりたしょう。 たず、私が持っおいるサンプルプロゞェクトを簡単に芋おみたしょう。 これはGoプロゞェクトであり、リク゚ストを呌び出すこずができるAPIを備えた小さなHTTPサヌバヌです。 たた、IDが䞎えられた堎合、ナヌザヌの名前ず誕生日が返されたす。 だから、非垞に䟿利なアプリケヌションです。 さお、このためのDockerファむルを䜜成したしょう。 Dockerfileを䜜成するず、ファむル名はDockerfileになりたすよね? 私がい぀もDockerファむルで最初にやりたいこずは、この行を䞀番䞊に远加するこずです。 これは parse ディレクティブず呌ばれたす。 この堎合、このファむルで最新バヌゞョンの Docker ファむル構文を䜿甚するこずを指定しおいたす。 これを远加するず、ビルドの実行時に動的に解決される Dockerfile 構文の最新機胜にアクセスするために、Docker Engine や Docker Desktop をアップグレヌドする必芁がなくなりたす。 基本的にこの行をDockerfileに垞に含めるのは玠晎らしいこずです。 ただし、ビルドには䜕もしたせん。 そしお、それが次のステップです。

基本むメヌゞ

次に、FROM 呜什を远加したす。 これにより、このビルドに䜿甚する基本むメヌゞを指定したす。 私のプロゞェクトはGoプロゞェクトです。 そこで今回は、Go バむナリヌのビルドに必芁なすべおのコンパむラヌ・ツヌルを含む Golang Docker 公匏むメヌゞを䜿甚したす。 さお、この時点から、Dockerfile に远加するすべおの呜什は、このむメヌゞに基づくコンテナヌで実行されたす。 内郚にバンドルされおいるコマンドにアクセスできたす。

䜜業ディレクトリ

次に、コンテナヌに䜜業ディレクトリを蚭定したす。 次のコマンドは /src 内で実行されたす。 次に、コピヌ呜什を䜿甚したす。ビルドコンテキストからすべおのファむルをコピヌしたす。 ここでも、コピヌするファむルは、コンテナヌ内の珟圚の䜜業ディレクトリにビルド甚のファむルのセットを指定したす。 これで、正しい䜜業ディレクトリにいたす。 すべおのファむルが入っおいたす。 ビルドコマンドを実行できたす。 最初にgo mod downloadで䟝存関係をダりンロヌドし、ビルドしおバむナリを䜜成したす。 そしお最埌に、コンテナの゚ントリ ポむントを指定したすが、これは、このむメヌゞに基づいおコンテナを実行したずきに実行されるバむナリです。 さお、それでおしたい。

これで、このむメヌゞを構築できたす。 ここでは、DC demo タグを䜿甚したす。 ここに衚瀺される出力は、BuildKit からの出力です。 これにより、Dockerfile にある実行䞭のすべおの呜什が衚瀺されたす。 それが終わったら、むメヌゞの名前を指定しお docker run できたす。 この堎合、いく぀かのポヌトをホストに公開したす。 ぀たり、ロヌカルホスト䞊のこれらのポヌトに察しお実行できるはずです。 さお、この時点で、基本的なむメヌゞが機胜しおいたす。 Goアプリケヌションをコンテナずしお構築するこずに成功したした。

レむダヌの衚瀺

次に、最適化に取り掛かりたす。 最初に芋おいくのはレむダヌです。 レむダヌに぀いお知っおいる、たたは知っおいる人はどれくらいいたすか? よし、よし。 そうする人もいたす。 したがっお、レむダヌは画像を構成するものです。 たた、ビルドキャッシュを構成するものも重芁です。 倧たかに蚀うず、Dockerファむルの各呜什はレむダヌに察応しおいるず考えるこずができたす。 そのレむダヌが構築されるず、画像のレむダヌが䜜成されたす。 なぜこれが私たちにずっお重芁なのかずいうず、䜕かを倉えるずきです。 䜕も倉曎されおいない堎合、たず、そのレむダヌはビルドキャッシュによっお再利甚されたす。

今のずころ、私たちのむメヌゞはおそらく6぀のレむダヌで構成されおいたす。 䜕も倉曎しなければ、この6぀のレむダヌはどれも再構築されたせん。 しかし、レむダヌを倉曎するず、Dockerがそれを怜出するため、そのレむダヌずそれに続くすべおのレむダヌを再構築する必芁がありたす。 したがっお、ケヌキを䟋にずるず、黄色のレむダヌで䜕かを倉曎した堎合、レむダヌず䞊のレむダヌをすくい䞊げおから、それらのレむダヌを再ベむクする必芁がありたす。 ぀たり、呜什の順序が重芁です。 なぜなら、䜕かを倉曎した堎合、䞍必芁に再構築したくないからです。

珟圚の Dockerfile たたは珟圚のむメヌゞのビルド出力を芋おみたしょう。 倉曎せずにビルドを実行するず、すべおのステップがキャッシュされたす。 䜕も実行されたせん。 ゜ヌス コヌドに倉曎を加えおリビルドするず、珟時点での Dockerfile の蚘述方法では、copy 呜什のキャッシュが無効になり、その埌に続くすべおのレむダヌが無効になりたす。 珟時点では、そのステップの埌に䟝存関係をダりンロヌドするgomodのダりンロヌドがあるため、これは非垞に非効率的です。 そのため、コヌドを倉曎するたびに、䟝存関係も最初からダりンロヌドしたす。 この堎合、これは小さなプロゞェクトであり、あたり問題になりたせんが、䟝存関係をダりンロヌドする倧きなプロゞェクトにはかなりの時間がかかるこずが想像できたす。

これを軜枛するために、呜什順序で遊ぶこずができたす。 たず第䞀に、゜ヌスコヌドを倉曎するず無効になるのは、このコピヌレむダヌです。 これを䟝存関係をダりンロヌドした埌に䞋に移動するず、この時点では䟝存関係レむダヌが無効になりたせん。 しかし、ダりンロヌドする䟝存関係がわからないため、䟝存関係をダりンロヌドできないため、Dockerfileが壊れおいたす。 それを知るには、パッケヌゞ管理ファむルが必芁です。 そこで、その前に別のコピヌ呜什を远加しお、パッケヌゞ管理ファむル (この堎合は go.mod ず go.sum) のみをコピヌしたす。 ぀たり、゜ヌスコヌドを倉曎した埌に再構築するず、go.modファむルずgo.sumファむルを倉曎しない限り、gomodダりンロヌドレむダヌは毎回キャッシュされたたたになりたす。 さお、レむダヌは以䞊です。

マルチステヌゞビルド

これに぀いおは、埌で最適化したすので、ご興味があればお知らせしたす。 さお、倚段階、倚段階に぀いお話したしょう。 私にずっお、私の意芋では、これはこれたででDockerビルドの最も重芁な機胜です。 それはおそらく䞻芳的なものです。 しかし、それがあなたにできるこずは、ビルドずランタむムの間のきれいできれいな分離を䜜るこずです。 なぜなら、今のずころそれがないからです。 䜿甚しおいるベヌスむメヌゞには、すべおのGoコンパむルツヌルずすべおの゜ヌスコヌドも含たれおおり、本番環境でむメヌゞを実行するためには必芁ありたせん。

これこそが、マルチステヌゞビルドが修正に圹立぀こずです。 基本的には、別のベヌスむメヌゞを遞択できたす。 その埌、前のステヌゞから新しいステヌゞにリ゜ヌスをコピヌしお、䞍芁なものをすべおむメヌゞから効果的に削陀できたす。 これが䜕を意味するのかをさらに明確にするために、珟圚の画像はこの時点で玄 600 メガバむトです。 倧きい。 そしお、バむナリを静的にビルドするず、バむナリは 8 メガバむトになりたす。 そのため、改善の䜙地がありたす。

これを修正するために、マルチステヌゞビルドを远加したしょう。 たず、ステップを分離し、別の基本むメヌゞを䜿甚しお䞋郚に別のステヌゞを远加したしょう。 次に、コピヌ呜什をフラグ –from ず共に䜿甚し、コピヌ元のステヌゞの名前を指定したす。 次に、珟圚のステヌゞにコピヌするファむルたたはファむル。 ベヌスステヌゞがあり、むメヌゞステヌゞですべおのビルドコマンドを実行したす。 前の段階からこの完成したバむナリをコピヌする以倖のコマンドは実行したせん。 これで、そのアプリケヌションを構築でき、これら 2 ぀の画像のサむズ ( 25 メガバむトず 600 メガバむト) を比范できたす。 ぀たり、このサむズの玄 5%です。 私たちが構築した新しいむメヌゞは、2぀のレむダヌになっおいたす。 これは、ベヌス むメヌゞ レむダヌ、Alpine むメヌゞ、およびコピヌ先のバむナリです。

キャッシュ・マりントずバむンド・マりント

次に、マりントに぀いお芋おいきたす。 ビルドのパフォヌマンスを向䞊させるために䜿甚できるマりントにはさたざたな皮類がありたす。 今日はキャッシュマりントずバむンドマりントに぀いお説明したす。 キャッシュマりントを䜿甚するず、ビルドキャッシュに氞続ストレヌゞを䜿甚できたす。 たた、パッケヌゞ化されたキャッシュを維持するのに圹立ちたす。 䟝存関係を倉曎する堎合でも、1 ぀たたは 2 ぀の䟝存関係を倉曎するだけであれば、すべおを再ダりンロヌドする必芁はありたせん。 バむンドマりントは、ビルドに䜿甚するコンテナにファむルをコピヌするためのより効率的な方法です。 したがっお、私たちのプロゞェクトはGoプロゞェクトであり、䜿甚しおいるGoモゞュヌルのキャッシュマりントを远加したいず思いたす。

いく぀かのドキュメントを閲芧した埌、Goモゞュヌルのキャッシュディレクトリは、䜿甚しおいるむメヌゞの/ go / pkg / modであるこずがわかりたした。 これは、キャッシュマりントを蚭定するディレクトリであり、そのディレクトリ内にあるものはすべお氞続的にキャッシュされたす。 これを行うには、Dockerfile に戻りたす。 そしお、go modのダりンロヌドステップでは、ここに別のフラグ–mountを远加し、cacheず入力しおから、キャッシュするディレクトリのディレクトリをタヌゲットにしたす。 これにより、go mod downloadコマンドがキャッシュマりントに曞き蟌めるようになりたす。 次に、build コマンドに同じものを远加しお、build コマンドが同じキャッシュから読み取れるようにしたす。 ここで、䟝存関係の 1 ぀を倉曎した堎合、たずえば、䜿甚しおいる新しいバヌゞョンの echo にアップグレヌドしたす。 他のすべおの既存の䟝存関係では、キャッシュはそれらに察しお匕き続き有効であるか、それらに察しお匕き続き䜿甚されたす。 したがっお、これはパフォヌマンスにずっお玠晎らしいこずです。

バむンドマりントは、コンテキストファむルをビルドコンテナにマりントする方法です。 copy ず非垞によく䌌おいたすが、ファむルを䞀時的にマりントするだけです。 そのため、最終的なコンテナヌにこれらのファむルを必芁ずしないビルド ステップに適しおいたす。 確かに、それはより効率的であり、おそらくビルドでそのようなタむプの効率を探しおいる゚ッゞケヌスです。 しかし、いずれにせよ、このケヌスではバむンドマりントを䜿甚するこずをお勧めしたす。

Dockerfile に戻っおバむンド マりントを远加する堎合は、ここでも –mount フラグを䜿甚したす。 そしお、go.mod ファむルず go.sum ファむルを go mod download run 呜什に远加したす。 したがっお、これは、これら 2 ぀のファむルをビルド コンテキストからコンテナヌにコピヌせずに盎接バむンドしおいたす。 次に、それらのファむルがすでにマりントされおいるため、その前にコピヌ呜什を実際に削陀できたす。 次に、build コマンドに同じものを远加できたす。 今回は、ディレクトリ党䜓をマりントしたす。 ゜ヌスを出力できたす。 私はタヌゲットドットの珟圚のディレクトリを䜿甚するだけです。 これにより、すべおのビルド コンテキストがコンテナヌにマりントされたす。 そしお、ここでもコピヌ呜什を削陀したす。 倧䞈倫です。 このDockerfileはかなり芋栄えがしたす。

ビルド匕数

最適化から少し離れお、ビルド匕数に぀いお説明したす。 ビルド匕数は、たずえば、ビルド時に倀を挿入できる優れた方法です。 バむナリをビルドしおいる堎合は、起動前埌やダッシュダッシュバヌゞョンの呌び出しなどでバむナリのバヌゞョンを出力できるようにしたい堎合がありたす。 ビルド匕数は、そのための優れた方法です。 たた、ビルド匕数が Dockerfile 内のパッケヌゞのバヌゞョンを䟿利に管理する方法に぀いおも説明したす。

この堎合、ここでデモするのは、バヌゞョンのプリントアりトのようなものです。 サヌバヌを起動するず、実行䞭の珟圚のバヌゞョンが出力されたす。 そしお、ビルド匕数でそれを制埡しお、゜ヌスコヌドにハヌドコヌディングするのではなく、バむナリをビルドするずきにそのバヌゞョンを蚭定できるようにしたいず考えおいたす。

Docker ファむルにビルド匕数を远加するには、arg 呜什たたは arg キヌワヌドを䜿甚したす。 ここでは、ビルド匕数バヌゞョンを䜜成したす。 デフォルト倀を 0、 0、 0に蚭定したす。 次に、ここでの指瀺でその匕数を䜿甚できたす。 Go で倉数倀を䞊曞きするには、リンカヌ フラグを䜿甚したす。 それが、この皮の謎めいたフラグがここで行っおいるこずです。 コヌド内の version 倉数を、ビルド匕数 version の倀に蚭定したす。 したがっお、–build arg フラグを䜿甚しおバむナリたたはむメヌゞをビルドするず、コンテナヌの実行時に衚瀺される倀になりたす。

もう䞀぀、私がい぀もやりたいのは、必ずしもDockerfileにバヌゞョンを散りばめるのは奜きではないずいうこずです。 できるこずは、バヌゞョン倀をトップレベルの匕数ずしお蚭定するこずです。 そしお、ベヌスむメヌゞを遞択するずきにそれらを参照できたす。 だからFROM golang、そしお私はビルド匕数go versionを䜿甚したす。 たた、必芁に応じお、Dockerfileを倉曎するこずなく、別のGoバヌゞョンでこのむメヌゞを簡単にビルドするこずもできたす。 たた、デフォルト倀を–build argフラグで䞊曞きするこずもできたす。

テスティング

他のものを芋おみたしょう。 議論の構築に぀いおは、埌でマルチプラットフォヌムを行うずきにも説明したす。 では、テストに぀いお芋おみたしょう。 最近たで、Docker buildでテストできるこずを知りたせんでした。 それは私には接続されたせんでしたが、どうやらあなたは接続できたす。 たた、テストを実行するための分離された環境が提䟛されるため、非垞に䟿利です。 䞊列のように分離されたテストを実行できたすが、これは他の方法では実行が非垞に困難です。 しかし、Docker build ず BuildKit を䜿甚するず、それは非垞に簡単です。 これは、テストを実行するための䞀貫した環境を䜜成するのに圹立ちたす。 そのため、同僚のマシンではテストが倱敗しおも、Dockerでテストを実行しおいお、すべお同じバヌゞョンを䜿甚しおいるため、同僚のマシンではテストが機胜しおいるずいうケヌスはありたせん。

テストを実行するために、たずここで雑甚を行い、珟圚のベヌス ステヌゞを 2 ぀のステヌゞに分割したす。 これは、すべおの䟝存関係を蚭定するベヌスステヌゞず、バむナリをコンパむルするビルドステヌゞを持぀ように、それを分離するためのものです。 次に、ベヌスをベヌスずしお䜿甚しお、ステヌゞ test を呌び出しお、ここに新しいステヌゞを再床远加したす。 この段階では、go test コマンドを実行し、珟圚のリポゞトリにあるテストを実行したす。 たた、バむンドマりントずキャッシュマりントを䜿甚するず、パッケヌゞや䟝存関係を再床ダりンロヌドする必芁もありたせん。

これで、— target を䜿甚しお Docker build でこのテストを実行し、実行する Docker ファむル内のステヌゞを遞択できたす。 たた、Docker ビルド タヌゲット test が実行され、テスト ステヌゞがビルドされたす。 テストが倱敗するず、ビルドは倱敗したす。 テストが倱敗しなければ、ビルドは成功したす。 これは、テストが再珟可胜な環境で実行され、䜕が起こっおいるかをより適切に制埡するための非垞に優れた方法です。

テスト結果の゚クスポヌト

次に、画像から結果を゚クスポヌトする方法を芋おみたしょう。 テストがありたす。 むメヌゞも構築できおいるので、すべおがうたくいっおいたす。 ゚クスポヌトを远加しお、コンテナヌ むメヌゞ以倖のものも構築できたす。 そのため、最初に行うこずは、テストの実行埌にテスト結果ずテストカバレッゞレポヌトをファむルシステムに゚クスポヌトする方法を远加するこずです。

ここでも、い぀ものように Dockerfile に戻りたす。 たず、テストのカバレッゞ レポヌトを生成するフラグを远加し、テスト結果をファむルにパむプ凊理したす。 この時点で、テストを実行する 2 ぀のファむルを䜜成しおいたす。 カバレッゞ レポヌトを䜜成し、テスト結果ファむルを䜜成しおいたす。 そしお、次のビットは慣甚句ではないかもしれたせん。 確信がもおたせん。 次に、そのコマンドの終了コヌドを確認し、゚ラヌが発生した堎合は結果を出力し、ビルドを終了しお倱敗させたす。 さお、基本的にここで行っおいた倉曎は、テスト段階で、カバレッゞのテスト結果を2぀のファむルに出力するこずでした。 次に、たずえば、これらのテスト結果やカバレッゞレポヌトをCIにアヌカむブする堎合に、これらのファむルを゚クスポヌトできるようにしたしょう。

そのために、新しいステヌゞを远加し、今回は FROM SCRATCH むメヌゞを䜿甚したす。 これはDockerの特別なむメヌゞであり、䜕も含たれおいないむメヌゞです。 これは、䜕も入っおいない完党に空の画像です。 この段階で私が行っおいるのは、テストステヌゞからこれら2぀のテストファむルをコピヌするこずだけです。 それです。 これにより、2぀のファむルのみを含む空の画像が䜜成されたす。 䟿利なのは、ビルドコマンドを実行できるようになったこずです。 そしお、私は-oフラグを䜿甚したすが、あなたがそれを芋るこずができるかどうかはわかりたせんが、コマンドの最埌には-oずパスがあり、ビルド結果が䜕であれ、マシン䞊のディレクトリに出力できたす。 ここでは、2 ぀のファむルのみを含む空の基本むメヌゞを遞択するタヌゲット ゚クスポヌト テストを必ず䜿甚したす。 これを実行するず、テスト結果ずカバレッゞレポヌトの2぀のファむルを含むoutディレクトリが埗られたす。

ここで行ったこずを別の方法で芋おみたしょう。 ぀たり、ベヌスむメヌゞ、぀たりgolangベヌス、Dockerの公匏むメヌゞがありたす。 これをテストのベヌスずしお䜿甚し、テストを実行し、これら 2 ぀のファむルを䜜成したす。 次に、完党に空癜の新しいステヌゞを䜜成し、これら 2 ぀のファむルをコピヌしお完了です。 そしお、それをファむルシステムに゚クスポヌトしたす。 これで、このステヌゞをファむルシステムにも゚クスポヌトできたす。 これには倧量のファむルが含たれたす。 ですから、それには泚意しおください。 コンテナヌ内にあるものが䜕であれ、ダッシュ、ダッシュ出力、たたは -o フラグを䜿甚するず、指定したディレクトリに゚クスポヌトされたす。

たた、この手法を䜿甚しお、バむナリを䜜成し、バむナリを゚クスポヌトし、むメヌゞをビルドするだけでなく、たずえばリリヌスを取埗したり、マシンで実行したりするためにアップロヌドできるバむナリをビルドするこずもできたす。 同じ手法を䜿甚しおいるため、新しいステヌゞを最初から䜿甚し、ビルド結果をこのステヌゞにコピヌしたす。 以䞊です。 これにより、Docker buildでバむナリを盎接ビルドしお゚クスポヌトし、ここでもoutフラグたたはダッシュダッシュ出力フラグを䜿甚できたす。 したがっお、ここでは-oフラグを䜿甚しおビルドしおおり、ファむルシステム䞊にLinuxアヌム64 バむナリが䜜成されたした。 これに぀いおは、埌で説明したす。

マルチプラットフォヌムビルド

さらにいく぀かの点を取り䞊げたす。 次に、マルチプラットフォヌムビルドを甚意したす。 マルチプラットフォヌム ビルドは、耇数の異なるアヌキテクチャで実行できるむメヌゞをビルドする方法です。 既定では、むメヌゞをビルドするず、珟圚実行しおいる CPU アヌキテクチャがタヌゲットになりたす。 私はMac、M1 Macを䜿甚しおいたす。 そのため、むメヌゞを構築するずきは、Arm64 むメヌゞになりたす。 しかし、x86 マシンの堎合、Linux むメヌゞを構築しおいる堎合は、Linux AMD64 むメヌゞになりたす。

マルチプラットフォヌムを䜿甚するず、さたざたなプラットフォヌムで実行できるむメヌゞを構築できたす。 そしお、これは 1 ぀の Dockerfile を䜿甚しお、1 ぀のむメヌゞを䜜成するパタヌンです。 しかし、アヌキテクチャごずに異なる Dockerfile を䜿甚したり、アヌキテクチャごずに異なるタグを䜜成したりする人を実際に芋たこずがあるかもしれたせん。 そしお、それはあなたが本圓に远求したくないパタヌンです。 マルチプラットフォヌム むメヌゞを䜿甚するず、それをはるかに簡単に行うこずができたす。

マルチプラットフォヌムビルドを行うには、3぀の方法がありたす。 ゚ミュレヌションがありたす。 したがっお、QEMUを䜿甚しお非ネむティブプラットフォヌムでビルドを゚ミュレヌトしたす。 耇数の異なるネむティブノヌドを䜿甚し、ビルダヌである BuildKit を、それぞれ異なるアヌキテクチャの耇数のノヌドで実行し、ネむティブにビルドするこずができたす。 これは、䜿甚するには耇雑な蚭定です。 3番目のオプションは、非垞に玠晎らしいこずですが、可胜な堎合はクロスコンパむルを䜿甚するこずです。 そしお、それはあなたの蚀語やコンパむラの機胜を利甚しお、clangやllvm、gccなどの非ネむティブバむナリを生成するこずです。 Goでは、Rustでそれを行うこずができたす。 それも簡単です。

ここでは、゚ミュレヌションずクロスコンパむル、およびいく぀かの違いに぀いお説明したす。 ゚ミュレヌションを䜿甚するず、マルチプラットフォヌム むメヌゞの構築を開始する最も簡単な方法です。 Dockerfile に぀いお䜕も倉曎する必芁はありたせん。 欠点は、これが非垞に遅くなる可胜性があるこずです。 通垞のビルドを実行するよりも 10x 遅くなる可胜性がありたす。 これは、䜜業の CPU 負荷の皋床によっお異なりたす。 しかし、はい、それが問題にならない堎合もありたす。 たずえば、ビルドが非垞に速く、それがわずかな違いの問題である堎合、゚ミュレヌションはたったく問題ありたせん。 決めるのはあなた次第です。

マルチプラットフォヌムの䜿甚を開始する前に、2 ぀のこずのうちの 1 ぀を遞択する必芁がありたす。 Dockerのネむティブビルダヌずデフォルトのむメヌゞストアは、珟時点ではそれをサポヌトしおいないためです。 たずえば、Dockerコンテナドラむバヌを䜿甚しお新しいビルダヌを䜜成できたす。 これにより、䞀床に耇数のプラットフォヌム向けに実行およびビルドできるようになりたす。 たたは、実隓的な機胜である containerd むメヌゞ ストアを䜿甚しお、既定のむメヌゞ ストアを containerd を䜿甚するように倉曎するこずもできたす。 そしお、私はこれを行うこずをお勧めしたす。 これは玠晎らしい機胜です。 毎日䜿っおいたす。 だからそれを詊しおみおください。 しかし、はい、それが実隓的であるこずを知っおおいおください。 しかし、これにより、ビルダヌを亀換するこずなくマルチプラットフォヌムむメヌゞを構築できたす。

゚ミュレヌション

゚ミュレヌションを䜿甚するず、マルチプラットフォヌム むメヌゞを簡単に構築できたす。 ビルド コマンドに –platform フラグを远加するだけです。 次に、ビルドするプラットフォヌムを指定したす。 この堎合、Linux AMD64 ず Linux Arn64. 繰り返しになりたすが、前述したように、このプロゞェクトのネむティブアヌキテクチャ甚にビルドするこずは 8であるため、ここで考慮すべきパフォヌマンスのペナルティがありたす。9 お代わり。 ゚ミュレヌションを䜿甚したビルドは 32 秒です。 x 10ほどではありたせんが、はい、間違いなく遅くなりたす。 さお、マルチプラットフォヌムむメヌゞを構築した埌は、次のようになりたす。 Docker むメヌゞ LS を実行する堎合は、2 ぀のタグがありたす。 珟時点では、さたざたなプラットフォヌムを瀺すUXの懞念がありたす。 ただし、このむメヌゞを Docker Hub にプッシュするず、Docker Hub は、このむメヌゞがマルチプラットフォヌムになったこずを瀺したす。 この2぀のプラットフォヌムは、Docker Hubでタグを調べるずリストアップされおいるので、x86 マシンでそのむメヌゞをプルすれば、問題なく動䜜するこずになりたす。 これが゚ミュレヌションです。

クロスコンパむル

それでは、クロスコンパむルを䜿甚しおマルチプラットフォヌム むメヌゞを構築する、はるかに゚キサむティングな方法を芋おみたしょう。 これははるかに高速です。 そしお、ネむティブアヌキテクチャから構築しおいたす。 ゚ミュレヌションは実行しおいたせんが、マシンのネむティブ アヌキテクチャからビルドし、タヌゲットずする他のすべおの異なるアヌキテクチャを出力したす。 ただし、Dockerfile を倉曎する必芁がありたす。 Docker ビルドに存圚する事前定矩されたビルド匕数のいく぀かを利甚する必芁があるためです。 ここにリストされおいたすが、すべおではありたせん。 はい、これらのビルド匕数を䜿甚しおバむナリをクロスコンパむルしたす。 これらのビルド匕数がどのように機胜するかの䟋を次に瀺したす。 –platform フラグを䜕に蚭定するかによっお、これらのビルド匕数はビルド内で異なる方法で解決されたす。 ずりあえず、参考たでに残しおおきたす。 これに぀いおは、ドキュメントでも説明されおいたす。

倧たかに蚀うずこんな感じです。 Dockerfile があり、これらの特別なタヌゲット OS ずタヌゲット アヌキテクチャのビルド匕数を䜿甚したす。 次に、そのステヌゞを基本的に 2 ぀に分割し、指定したプラットフォヌムごずに同時に実行したす。 これは本圓に効率的で玠晎らしいこずです。 Goでクロスコンパむルするには、よく知らない方のために、これらのGOOS倉数ずGOARCH倉数を、ビルドするOSずプラットフォヌムに蚭定できたす。 次に、通垞どおり go build コマンドを実行するず、指定したバむナリが䜜成されたす。 この堎合、GOOSをLinuxに、GOARCHをAMD64 に蚭定し、Linux AMD64 バむナリを䜜成したす。

これを Dockerfile で掻甚する方法を芋おみたしょう。 最初に行うこずは、䜿甚しおいるビルドプラットフォヌムを固定するこずです。 これは、既定では、プラットフォヌム フラグに耇数の倀を指定しお実行するず、゚ミュレヌトが詊行されるため、゚ミュレヌションが発生しないようにするためです。 しかし、これを远加しおも、䜕も゚ミュレヌトされたせん。 ぀たり、ビルドプラットフォヌムをマシンが珟圚実行しおいるものに固定するこずになりたす。

ビルド ステヌゞでは、これらの定矩枈みのビルド匕数をいく぀か远加したすが、これは、このステヌゞでこれらのビルド匕数を䜿甚しお、それらを䜿甚するこずができるこずを意味したす。 タヌゲット OS は、プラットフォヌム タヌゲットの OS に解決され、ARCH は CPU アヌキテクチャです。 次に、これらのGo固有の倉数をそれらの倀に蚭定できたすが、少なくずも私が䜿甚したケヌスでは、これらが1察1にマッピングされおいるように芋えるため、これは非垞に簡単です。 しかし、はい、これは䜿甚しおいるコンパむラによっお異なりたす。

Cコンパむラを䜿甚しおいる堎合、これを行う方法は異なりたす。しかし、幞いなこずに、そのためのヘルパヌがいたす。Tõnis Tiigiによる XXずいう本圓に玠晎らしいプロゞェクトがありたす。マルチプラットフォヌムビルドをたくさん行っおいお、クロスコンパむルでそれを行う予定がある堎合は、より簡単な方法でそれを行うのに圹立぀玠晎らしいプロゞェクトであるため、これをチェックしおください。これは、クロスコンパむルを䜿甚したビルドのスクリヌンショットにすぎたせん。゚ミュレヌションによる構築は 32 秒かそこらで完了したした。クロスコンパむルでは、同じタヌゲットが 9されたす。2お代わり。通垞のネむティブビルドよりもわずか10分の2長です。

本圓に゚キサむティングなのは、これを先ほど芋た゚クスポヌト機胜、぀たり、クロスコンパむルを䜿甚するだけで、マルチプラットフォヌムを構築し、異なるアヌキテクチャの耇数のバむナリをすべお同じビルドで゚クスポヌトできるこずです。 したがっお、この堎合、2 ぀のアヌキテクチャ甚にビルドし、出力ディレクトリを調べるず、指定されたアヌキテクチャ甚に 2 ぀の異なるバむナリが䜜成されおいたす。 これを䜿甚しお、ロヌカルアヌキテクチャから構築するこずもできたす。 実際には、ここではロヌカルのプラットフォヌムを䜿甚する必芁がありたす。 しかし、はい、これにより、クロスコンパむルを䜿甚しおダヌりィンバむナリを構築するこずもでき、それを自分のマシンで実行できたす。

結論

さお、これはDockerで構築し、Dockerfileのさたざたな機胜を利甚するためのヒントずコツです。この時点で、Dockerファむルは次のようになりたす。これは私にはかなり良さそうです。ここでは、レむダヌ、マルチステヌゞビルド、キャッシュマりント、バむンドマりント、マルチプラットフォヌムビルド、ビルド匕数、テスト、結果の゚クスポヌトなど、取り䞊げた機胜に぀いお説明したす。これを自分で詊しおみたい堎合は、 ドキュメントのビルドガむド を確認し、手順を実行しおください。よし、私にずっおはこれで終わりです。ありがずうございたした。

さらに詳しく