Docker テクノロジーは、2013 年の誕生以来 4 年以上にわたって存在しています。日常の開発作業で Docker テクノロジーを受け入れて使用してきた開発者にとって、Docker イメージの構築は当たり前のことになっています。しかし、これは Docker のイメージ構築メカニズムが比較的完璧であることを意味するのでしょうか?いいえ、Docker の担当者はイメージ構築メカニズムを継続的に最適化しています。今年リリースされた Docker 17.05 バージョン以降、Docker はコンテナ イメージのマルチステージ ビルドのサポートを開始しました。 多段階イメージ構築とは何ですか?概念を直接定義するのはあまりにも唐突なので、ここでは秘密にしておきましょう。まず、日常の開発で使用されるイメージ構築方法と、イメージ構築で遭遇する問題から始めましょう。 1. 同型画像の構築 イメージを構築する際の一般的なシナリオは、アプリケーションが開発者自身の開発マシンまたはサーバー上で直接コンパイルされ、コンパイルされたバイナリ プログラムがイメージにインストールされるというものです。このような状況では通常、コンパイル環境がイメージで使用されるベース イメージと互換性があることが必要です。たとえば、Ubuntu 14.04 でアプリケーションをコンパイルし、Ubuntu シリーズのベースイメージに基づいたイメージにアプリケーションを配置します。アプリケーションのコンパイル環境は、それがデプロイされ実行される環境と互換性があるため、私はこの種のビルドを「同型イメージ ビルド」と呼んでいます。つまり、Ubuntu 14.04 でコンパイルしたアプリケーションは、ubuntu:14.04 以降のバージョン (例: 16.04、16.10、17.10 など) に基づくベース イメージでほぼシームレスに実行できます。ただし、Centos などの互換性のないベース イメージでは実行に失敗する可能性があります。 1. 均質画像構築の例 ここでは、均質なイメージを構築する例を示します (以降の章もこの例に基づいています)。注: コンパイル環境は、Ubuntu 16.04 x86_64 仮想マシン、Go 1.8.3、Docker 17.09.0-ce です。 Go で最も一般的な http サーバーを例として使用してみましょう。
このプログラムをコンパイルします:
この例は、数行のコードしかないため単純に見えますが、Go の net/http パッケージは、多くのシステム コールを含む多くの作業を最下層で実行します。これは、アプリケーションとオペレーティング システム間の「結合」を反映するもので、以降の説明で反映されます。次に、このプログラム用の Docker イメージを構築し、このイメージに基づいて myhttpserver コンテナを起動します。ベースイメージとしてubuntu:14.04を選択します。
ビルドを実行します。
上記は最も基本的なイメージ構築方法です。 次に、次の要件に遭遇する可能性があります。 * Go プログラムのビルド環境の設定は、特に多くのサードパーティのオープンソース パッケージに依存する Go アプリケーションの場合、時間がかかることがあります。パッケージのダウンロードには長い時間がかかる場合があります。 Go プログラム構築のために、これらすべての変更可能なものをビルダー イメージにパッケージ化するのが最善です。 * 上記で作成した myrepo/myhttpserver イメージのサイズは 200 MB であり、少し「大きすぎる」ようです。各ホストノード上の Docker にはイメージレイヤーをキャッシュする機能がありますが、より簡潔でコンパクトなイメージを構築したいと考えています。 2. Golang ビルダーイメージの使用 Docker Hub は、Go 開発環境を備えた公式の Golang イメージ リポジトリを提供します。この Golang ビルダー イメージを直接使用して、アプリケーション イメージを構築できます。サードパーティのパッケージに大きく依存する一部の Go アプリケーションでは、この golang イメージをベース イメージとして使用して、専用のビルダー イメージをカスタマイズすることもできます。 golang:latest ベースイメージに基づいて golang-builder イメージをビルドします。 golang-builder イメージをビルドするために Dockerfile.build を記述します。
同じディレクトリに golang-builder イメージをビルドします。
次に、golang-builder で構築された myhttpserver に基づいて最終的なアプリケーション イメージを構築します。
このコマンドのロジックは、golang-builder イメージに基づいて起動されたコンテナ appsource からビルドされた myhttpserver をホストの現在のディレクトリにコピーし、その後、上記でビルドされた一時コンテナ appsource と golang-builder イメージを削除することです。最後の手順は最初の例と同じで、ローカル ディレクトリに構築された myhttpserver に基づいて最終イメージを構築します。便宜上、この一連のコマンドを Makefile に入れることもできます。 3. 小さめのアルプスの画像を使用する ビルダー イメージは、最終的なアプリケーション イメージの重量を軽減するのに役立ちません。 myhttpserver イメージのサイズは 200 MB のままです。 「軽量化」するには、ベースイメージを小さくする必要があり、アルパインを選択しました。アルパイン画像のサイズは4M未満です。アプリケーションのサイズを追加すると、最終的なアプリケーション イメージのサイズは 20 MB 未満に縮小されると推定されます。 ビルダーイメージを結合するには、Dockerfile のベースイメージを alpine:latest に変更するだけです。
アルパイン バージョンのアプリケーション イメージをビルドします。
16.3MB、確かにサイズが小さくなりました!このイメージに基づいてコンテナを起動し、アプリケーションの実行に問題がないか確認します。
コンテナの起動に失敗しました。なぜ? alpine イメージは ubuntu 環境と同じではないためです。これについては以下で詳しく説明します。 2. 異種画像構築 私たちのイメージ ビルダー: myrepo/golang-builder:latest は、golang:latest イメージに基づいています。 golang ベースイメージには、Dockerfile-debain.template と Dockerfile-alpine.template の 2 つのテンプレートがあります。 golang:latest は Debian テンプレートに基づいており、Ubuntu と互換性があります。構築された myhttpserver には、動的共有リンク ライブラリに対して次の条件があります。
Debian ベースの Linux ディストリビューションは glibc を使用します。しかしアルパインは違います。 Alpine は musl libc の実装を使用します。したがって、上記のコンテナを実行すると、myhttpserver が依存する libc.so.6 が見つからないため、ローダーは終了に失敗します。 このようにビルド環境と実行環境が互換性のない状態を「異種イメージビルド」と呼びます。では、この問題をどう解決すればよいのでしょうか?続けましょう: 1. 静的ビルド 主流のプログラミング言語の中で、Go はすでに移植性の点で最高の言語の 1 つです。特に、ランタイムのすべての C コードが Go で書き直され、libc への依存が最小限に抑えられた Go 1.5 以降では、移植性がさらに向上しました。ただし、一部の機能では、C 実装と Go 実装の 2 つの実装バージョンがまだ提供されています。デフォルトでは、つまり CGO_ENABLED=1 の場合、プログラムとプリコンパイルされた標準ライブラリの両方が C 実装を使用します。この点に関する詳細な議論については、私の以前の記事「Go の移植性についても」を参照してください。ここでは詳細には触れません。したがって、異なる libc 実装を使用する Debian システムと Alpine システムの間には、当然ながら非互換性があります。この問題を解決するために、まず Go プログラムを静的にビルドし、次に静的にビルドされた Go アプリケーションを alpine イメージに配置することを検討します。 Dockerfile.build を変更し、Go ソース ファイルをコンパイルするときに CGO_ENABLED=0 を追加しましょう。
このビルダーイメージをビルドします:
次に、golang-static-builder で構築された静的に接続された myhttpserver に基づいて、最終的なアプリケーション イメージを構築します。
新しいイメージを実行します。
注: strace を使用すると、Go が静的にリンクするときに独自のランタイム実装のみを使用し、libc.a のコードを使用しないことを証明できます。
go-static-build-strace-file-open.txt ファイルを開き、その内容を確認します。 libc.a ファイルは見つかりません (Ubuntu では、libc.a は通常 /usr/lib/x86_64-linux-gnu/ にあります)。これは、go build が libc.a ファイルを開いてその中のシンボル定義を取得しようとしなかったことを意味します。 2. alpine golangビルダーを使用する 私たちの Go アプリケーションは、alpine ベースのコンテナーで実行されます。 alpine golang ビルダーを使用してアプリケーションをビルドできます (静的リンクなし)。前述したように、golang には alpine テンプレートがあります。
golang ビルダーの alpine バージョンの Dockerfile の内容は次のとおりです。
以降の操作は、前の golang ビルダーと同じです。alpine golang ビルダーを使用してアプリケーションをビルドし、alpine イメージに配置します。ここでは詳細には触れません。 3. 多段階イメージ構築:開発者エクスペリエンスの向上 Docker 17.05 より前では、上記のようにイメージを構築していました。異種イメージ ビルダー モードを使用する場合でも、2 つの Dockerfile を維持し、コンテナーからのアプリケーションのコピー、ビルド コンテナーのクリーンアップ、イメージのビルドなど、docker build コマンドの外部でいくつかの操作を実行する必要があることがわかります。 Docker コミュニティはこの問題を認識し、マルチステージ イメージ構築メカニズム (マルチステージ) を実装しました。 まず、上記の例のマルチステージ ビルドに使用される Dockerfile を見てみましょう。
この Dockerfile の内容を読んだ後の第一印象は、前の 2 つの Dockerfile が結合され、各 Dockerfile が個別の「ステージ」になっているということです。確かにその通りですが、この Docker には、さまざまな「ステージ」間の接続を確立するための新しい構文形式もいくつかあります。このような Dockerfile については、次の点を知っておく必要があります。
上記の例をマルチステージを使用して構築してみましょう。
この画像を実行してみましょう:
IV.まとめ マルチステージイメージ構築により、開発者は Dockerfile を使用して一度に小さなイメージをより簡単に構築できるようになり、優れたユーザーエクスペリエンスが提供され、CI/CD などの自動化システムへの接続が容易になります。ただし、現在、マルチステージ ビルドは Docker 17.05 以降のバージョンでのみサポートされています。この機能を学習して練習したいが環境がない場合は、play-with-docker が提供する実験環境を使用できます。 |
<<: 恒源智成とアリババクラウドが共同でビジネスチェーン全体をカバーするダブル11クラウドカーニバルを開始
Hostus、新年のプロモーション、ここでは大容量メモリを備えた特別なVPSのみを選択します。母鶏は...
Sina Weibo 幹部チーム (写真提供: Tencent Technology)テンセントテク...
クラウド コンピューティングをどのように使用するかは、企業のアプリケーション戦略アーキテクチャと計画...
Egihosting はストレージベースの VPS を開始しました。必要な場合はぜひご覧ください。デ...
ショッピングモールサイトである瑞品モールは、主に写真形式のウェブサイトです。お茶業界のインテグレータ...
今年の天猫ダブル11プレセール初日には、約10万人のタオバオキャスターが放送を開始し、約2万のブラン...
2019年へのカウントダウンが始まりました。クラウド コンピューティング市場を振り返ると、変化と課題...
SEO担当者は、オリジナルコンテンツの作成、外部リンクの作成、画像の作成など、毎日やるべきことがたく...
大規模なハッキングやエクスプロイトを準備する際、サイバー攻撃者は自身のスキルや狡猾さよりも、被害者の...
最近、偶然、Lu Songsong 氏の「有名なブログを作るにはどのくらいの時間がかかりますか?」と...
ウェブサイトのユーザーエクスペリエンスを向上させることに関しては、多くの SEO 担当者は無知です。...
SEO 最適化を始めたばかりの方は、検索エンジン スパイダー (検索エンジンが Web ページをクロ...
ソーシャル分野では、Facebook がインターネット発展の歴史におけるユニークな花となり、Pint...
みなさんこんにちは。A5でまたお会いできて嬉しいです。上記で公開した 2 つの記事は 1,000 回...
ほとんどのウェブマスターの目には、Baidu がウェブサイトの記事を組み込むのは、その質が優れている...