Docker マルチステージビルドを使用してイメージサイズを縮小する方法

Docker マルチステージビルドを使用してイメージサイズを縮小する方法

この記事では、Docker のマルチステージ ビルド機能を使用してイメージ サイズを大幅に削減する方法について説明します。これは、Dockerfile でプログラム (javac など) をビルドする必要があり、コンパイル ツール チェーンのインストールが必要なイメージに適しています。 (Javaなど)

まずは単語を覚えましょう(この記事では中国語の語彙を使用しています。外国の文書を調べる必要がある場合は、この語彙リストを参照してください。理論的には、私は個人的に用語を翻訳することに賛成しません)。

  • 多段階
  • 建てる
  • 画像
  • ステージ

効果を見てみましょう。当初は 1 億 1,000 万以上でしたが、現在は 9,200 万です。

Dockerfileを比較する

最適化前の Dockerfile:

openjdk:8u171-jdk-alpine3.8 から

./app を追加する
ワークディレクトリ /app

apk add maven を実行 \
  && mvn クリーンパッケージ \
  && Maven の apk \
  && mv target/final.jar / \
  && CD / \
  && rm -rf /app \
  && rm -rf /root/.m2

エントリポイント java -jar /final.jar

最適化された Dockerfile:

openjdk:8u171-jdk-alpine3.8 からビルダーとして

./app を追加する
ワークディレクトリ /app

apk add maven を実行 \
  && mvn クリーンパッケージ \
  && Maven の apk \
  && mv ターゲット/final.jar /

環境としてopenjdk:8u181-jre-alpine3.8から
ワークディレクトリ /
--from=builder /final.jar にコピーします。
エントリポイント java -jar /final.jar

明らかに、最適化された Dockerfile には FROM AS コマンドが追加され、2 つの FROM が表示されます。これは多段階のビルドです。

マルチステージビルドについて学ぶ

マルチステージ ビルドは Docker 17.05 の新機能であり、Dockerfile 内で複数の FROM ステートメントを使用して複数のステージを作成できます。各ステージは独立しており (ソース要求)、他のステージのファイルは COPY --from を通じて取得できます。最終的なイメージを料理(ピーマンのフライ)に例えてみましょう。生のピーマンを揚げたら出来上がりです。

# 比較リストミラー -> 料理第一段階 -> 炒め物第二段階 -> 盛り付ける

2 つのステージの目標は、最終的な料理 (画像) を作成 (生成) することです。私たちがすべきことは、最初の段階で「揚げた」食べ物を提供することです。私たちの目標は、できるだけ軽い皿(盛り付け用および中間製品)で料理を作ることです。

視覚化プロセスは次のとおりです。

# 調理プロセス...材料を省略-> [第一段階-炒める] # この時、皿の上には炒め物、炒め物、中間製品があります # この時、第二段階を開始し、炒め物だけを残し、他のものは必要ありません。
-> 炒めた結果-> [盛り付け開始、結果のみ保存] # 炒めたピーマン(COPY --from)を取り、他は取らない-> 完成した料理は一品です。

これで、マルチステージ ビルド プロセスの概要を理解できたはずです。マイクを Java に渡して、Dockerfile のコンパイル ツールを使用して JAR をビルドし、ビルドされた JAR とランタイムのみを保持して Image に渡し、残りを破棄する方法を見てみましょう。

# フェーズ 1 - コンパイル (フライ)
FROM openjdk:8u171-jdk-alpine3.8 as builder # 組み込みコンパイルツール ADD ./app
ワークディレクトリ /app

実行...コンパイルとクリーンアップをスキップ...

# これで、JAR がリリースされました。 JDK は不要になったため、イメージ内に残すことはできません。
# そこで、第2段階(デスクトップ上で実行)を開始し、第1段階のすべてのファイル(コンパイルツールを含む)を破棄します。
FROM openjdk:8u181-jre-alpine3.8 as environment # ランタイムのみ# 現時点では、前段階のコンパイル ツールなどは放棄されています。現在のイメージでは、実行時にのみ、前の段階 (揚げる) の結果を取得する必要があり、他の段階は必要ありません。
--from=0 /final.jar をコピーします。

# これで、イメージには必要なランタイムと JAR のみが含まれるようになりました。
エントリポイント java -jar /final.jar

以上が多段階施工の紹介です。

マルチステージビルドの使用

マルチステージビルドのコアコマンドは FROM です。多くの戦いを経験してきたあなたにとって、FORM についてはあまり説明する必要はありません。マルチステージ ビルドでは、各 FROM によって新しいステージが開始されます。これは、他のステージ (環境変数も含む) から分離された新しいイメージ (正確性は低い、ソース要求) として表示されます。イメージには最後の FROM のみが含まれます。

簡単なマルチステージビルドの例を作ってみましょう。

# ステージ1
アルパインから:3.8
WORKDIR /デモ
RUN echo "Hello, stage 1" > /demo/hi-1.txt

# ステージ2
アルパインから:3.8
WORKDIR /デモ
RUN echo "Hello, stage 2" > /demo/hi-2.txt

この Dockerfile を自分でビルドし、 docker save <tag> > docker.tar を実行して内容を確認することができます。何も問題がなければ、/demo/hi-2.txt と Alpine のみが存在するはずです。

この Dockerfile では、 2 つのステージを作成しました。最初のステージでは hi-1.txt が作成され、2 番目のステージでは hi-2.txt が作成されます。最終イメージには 2 番目のステージが追加されますが、他のステージは追加されません。

ファイルのコピー - ステージ間の橋渡し

ステージが互いに完全に分離されている場合、複数のステージを持つ意味はありません。前のステージの結果は完全に破棄され、次の完全に新しいステージに入ります。

COPY コマンドを使用して、他のステージからファイルを取得できます。複数のステージで COPY を使用する方法は通常のアプリケーションとまったく同じで、 --form ` を追加するだけです。次に、最終画像に 2 つのステージの成果物が含まれるように前の例を変更します。

# ステージ1
アルパインから:3.8
WORKDIR /デモ
RUN echo "Hello, stage 1" > /demo/hi-1.txt

# ステージ2
アルパインから:3.8
WORKDIR /デモ
コピー --from=0 /demo/hi-1.txt /demo
RUN echo "Hello, stage 2" > /demo/hi-2.txt

再構築して保存(保存)すると、hi-1.txt を含む追加のレイヤーが見つかります。

ステージ名 - 迅速な識別

記憶力が 7 秒しかない私たちにとって、ステージ インデックスを毎回使用するのはあまり良いことではありません。このとき、ステージに名前を付けて識別しやすくしておくといいでしょう。

ステージに名前を追加するのは簡単です。FROM の後に <name> を追加するだけです。

ここで、Dockerfile を更新してステージに名前を付け、その名前を使用して COPY します。

# ステージ 1、名前は「build1」です
alpine:3.8 から build1 へ
WORKDIR /デモ
RUN echo "Hello, stage 1" > /demo/hi-1.txt

# ステージ 2、名前は「build2」です
alpine:3.8 から build2 へ
WORKDIR /デモ
# インデックスは使用しなくなりました
コピー --from=build1 /demo/hi-1.txt /demo
RUN echo "Hello, stage 2" > /demo/hi-2.txt

再構築して保存すると、結果は前回と同じになるはずです。

一部のステージのみを構築 - デバッグが簡単

Docker は、ステージの一部のみをビルドするという非常に便利なデバッグ方法も提供します。特定の段階でビルドを停止し、後続の段階をビルドしないようにすることができます。これにより、デバッグが容易になり、本番環境、開発環境、テスト環境を区別できるようになります。

最後の Dockerfile を引き続き使用しますが、ビルドには --target <stage> パラメータを使用します。

ビルドを --target として実行します。

もう一度保存すると、build1 の内容だけが見つかります。

要約する

マルチステージビルドについては以上です。冒頭の 2 つの Dockerfile に戻って比較してみましょう。最適化前のイメージのどこが太っているのかわかりますか?

当然、コンパイル時にのみ動作し、コンパイル後は役に立たない、役に立たない JDK が含まれています。必要なのは JRE だけです。したがって、マルチステージ ビルドを使用すると、コンパイル ステージと実行ステージを分離してイメージの最適化を実現できます。

参考文献

https://docs.docker.com/develop/develop-images/multistage-build/#ビルドステージ名

https://yeasy.gitbooks.io/docker_practice/image/multistage-builds.html

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Dockerイメージサイズを最適化する一般的な方法
  • Dockerイメージのサイズを縮小する6つの方法

<<:  jsはjQueryをカプセル化する簡単な方法とチェーン操作の詳細な説明を実装します

>>:  MySQLトリガーの使用例の詳細

推薦する

ウェブ開発で遭遇した問題と経験

<br />以下は開発中に遭遇した問題と、そこから得た経験です。デバッグに時間がかかりま...

Vue3 コンポジション API でロジックの再利用を実装する方法

Composition API はロジック再利用手順を実装します。ロジックコードを関数に抽出します。...

JavaScriptの無限ループを検出して防止する方法の詳細な説明

目次序文for文の無限ループを修正while文の無限ループを修正要約する序文Js デッド ループはど...

1つの記事でJavaScriptのクロージャ関数について学ぶ

目次変数のスコープ閉鎖の概念クロージャの使用クロージャのデメリット最後に、クロージャのメリットとデメ...

例を通してMySQLの更新がテーブルをロックするかどうかを判定する

2つのケース: 1. 索引あり 2. 索引なし前提条件:方法: コマンドラインを使用してシミュレート...

CSS flex 複数列レイアウト

基本的な3列レイアウト 。容器{ ディスプレイ: フレックス; 幅: 500ピクセル; 高さ: 20...

Linuxホスト名変更コマンドの詳しい説明

Linux ホスト名変更コマンド1. ホスト名を一時的に変更するだけの場合は、hostname コマ...

Vue+element+oss はフロントエンドのフラグメントアップロードとブレークポイント再開を実現します

純粋なフロントエンド実装:切片上傳斷點續傳。斷點續傳カットとアップロードに基づいて実装する必要があり...

Vue Element フロントエンドアプリケーション開発のための従来の JS 処理機能

目次1. 従来のコレクションに対するフィルター、マップ、および削減処理方法2. 再帰処理3. for...

MySQL sql99構文の内部結合と非等価結合の詳細な説明

#事例: 従業員の給与水準を照会する 選択 給与、等級 から 従業員 参加する ジョブグレード g ...

HTML テーブルタグチュートリアル (32): セルの水平方向の配置属性 ALIGN

水平方向では、セルの配置を左、中央、右に設定できます。基本的な構文<TD ALIGN=&quo...

mysql 解凍パッケージの基本インストールチュートリアル

新しいコンピューターに変更したので、すべての環境を新しいコンピューター上で設定する必要があります。ふ...

Vue が Ref を使用してレベル間でコンポーネントを取得する手順

VueはRefを使用してレベル間でコンポーネントインスタンスを取得します例の紹介開発プロセスでは、レ...

MySQLの文字セット設定を5分で理解しましょう

目次1. コンテンツの概要2. 文字セットと文字順序の概念と関係3. MySQL でサポートされてい...

Vueはvueメタ情報を使用して各ページのタイトルとメタ情報を設定します。

title: vue は vue-meta-info を使用して各ページのタイトルとメタ情報を設定...