web-dev-qa-db-ja.com

Dockerレイヤーの数を最小限に抑える必要がありますか?

documentation は、このトピックについて詳しく説明していません。それは言います:

レイヤーの数を最小限に抑える

Docker 17.05より前、さらにDocker 1.10より前では、画像のレイヤー数を最小限に抑えることが重要でした。以下の改善により、この必要性が緩和されました。

Docker 1.10以降では、RUN、COPY、およびADD命令のみがレイヤーを作成します。他の命令は一時的な中間イメージを作成し、ビルドのサイズを直接増加させなくなりました。

Docker 17.05以降では、マルチステージビルドのサポートが追加され、必要なアーティファクトのみを最終的なイメージにコピーできます。これにより、最終イメージのサイズを増やすことなく、ツールとデバッグ情報を中間ビルドステージに含めることができます。

最新のDockerバージョンでは、多くのレイヤーを処理する問題を解決できないようです。彼らはむしろ最終的な画像の数を減らすよう努めています。最も重要なことは、ドキュメントは多くのレイヤーが悪いということをwhyとは言わないことです。

42層の AUFS制限 を知っています。広く使用されている画像の場合、レイヤーの上に構築された他の画像が制限に適合するので、レイヤーの数を少なくすることは理にかなっています。ただし、他の目的のために別のストレージドライバーとイメージがあります。

また、明らかな理由で画像を小さく保つことは良いことです-ディスク領域とネットワーク帯域幅を占有します。ただし、 連鎖RUNステートメント とは思わないため、多くのレイヤーを1つに押しつぶすことは一般に役立ちます。異なるRUNがファイルシステムの異なる部分を更新する場合、1つのレイヤーと多くのレイヤーを合わせてほぼ同じサイズにする必要があります。

一方、多くのレイヤーでは、キャッシュを使用してイメージを再構築することができます。それらも並行してプルされます。

私は、プライベートDockerレジストリを使用して小さなチームで働いています。 42層の制限に対応することはなく、パフォーマンスと開発速度を重視します。

その場合、ドッカーレイヤーの数を最小限に抑える必要がありますか?

21
gukoff

私は、プライベートDockerレジストリを使用して小さなチームで働いています。 42層の制限に対応することはなく、パフォーマンスと開発速度を重視します。

その場合、ドッカーレイヤーの数を最小限に抑える必要がありますか?

あなたの場合、いいえ。
最小化する必要があるのはビルド時間です。つまり、次のことを意味します。

  • 最も一般的な手順と最も長い手順を最初に確認してからキャッシュし、Dockerfileの最後の行(最も具体的なコマンド)をいじりながら、すばやく再構築できるようにします。
  • 最長のRUNコマンドが他のRUNコマンドと連鎖するのではなく、最初に独自のレイヤーに(再びキャッシュされる)ことを確認します。これらの1つが失敗した場合、長いコマンドを再実行する必要があります。その長いコマンドが独自の(Dockerfile行)/レイヤーで分離されている場合、キャッシュされます。

つまり、 あなたが言及したドキュメントdocker/docker.github.io 、正確に PR 4992 および PR 4854docker build LABELセクション
したがって、このセクションはLABELについての同様の発言の後にあり、レイヤーを作成するコマンドを強調しています。
再び、あなたの場合、それは重要ではないでしょう。

20
VonC

複数のRUNで作成されたイメージと、1つのRUN連結コマンドで作成されたイメージの2つのイメージの違いを確認したかっただけです。

最初のケースでは、画像は些細な操作(ファイルの作成と削除)を行っています。

「シングル」レイヤー画像のコンテンツ:

FROM busybox

RUN echo This is the 1 > 1 \
    && rm -f 1 \
    && echo This is the 2 > 2 \
    && rm -f 2 \
# ... for about 70 commands

複数レイヤーの画像のコンテンツ:

FROM busybox

RUN echo This is the 1 > 1
RUN rm -f 1
RUN echo This is the 2 > 2
RUN rm -f 2
# ... for about 70 layers

ビルド時間は大きく異なります(複数:0m34,973s、単数:0m0,568s)。コンテナの起動時間も異なりますが、目立ちません(複数:0m0,435s、単数:0m0,378s)。画像を異なる時間で実行しましたが、時間はそれほど変わりません。

スペースに関しては、マルチレイヤーの場合の最悪のケースを意図的に調べましたが、予想どおり、マルチレイヤーイメージはシングルレイヤーよりも大きくなっています。

別のテストでは、画像にコンテンツのみを追加するレイヤーを連結しました。ビルド時間は前の場合と変わりませんが、実行時の場合は少し異なります。マルチレイヤーイメージは、シングルレイヤーイメージよりも起動が高速です。スペースに関しては、同じ結果です。

私はこれが何かを証明するとは思わないが、私はそれをやって楽しんでいた:P

17
Stefano

レイヤーの数を減らすことは、目標そのものではありません。むしろ、集中する必要があるのは、ビルド時間を短縮し、イメージサイズを縮小することです。

Dockerfileの最上部またはベースイメージ内でほとんど変更されない一般的なレイヤーを保持することにより、ビルド時間を短縮します。これにより、レイヤーをキャッシュし、後のビルドで再利用できます。これは、レイヤーの数を減らすことではなく、レイヤーを適切に順序付けることです。

イメージサイズを小さくすると、レジストリシステムでのディスク使用量を減らすのに役立ちます。レジストリサーバーでは、CIシステムのビルドごとにイメージが保存されるときにディスクに大きなヒットが発生します。また、イメージを転送するためのネットワーク時間も短縮されます。大きな一時ファイルをダウンロードする1つのレイヤーがあり、それを別のレイヤーで削除すると、ファイルが最初のレイヤーに残され、ネットワーク経由で送信されてディスクに保存されます。コンテナ。ファイルのアクセス許可を変更すると、ファイルが新しいアクセス許可で現在のレイヤーにコピーされ、そのファイルのディスク容量とネットワーク帯域幅が倍になります。

上記のシナリオで画像サイズを縮小する標準的なソリューションは、RUNコマンドを連鎖させて、一時ファイルが画像レイヤーに保存されないようにすることです。これには、画像レイヤーの数を減らすという副作用があります。

最後の問題が1つあります。それは過剰なキャッシュです。これは、Debianイメージのapt-get updateおよびapt-get install ...コマンドでよく見られます。これらのコマンドを連結しない場合、apt-get installコマンドの更新により、以前のレイヤーapt-get updateコマンドの古いキャッシュが再利用され、数か月後に必要なパッケージが見つからない場合に失敗します。したがって、ビルド時間が長くなる場合でも、これらのコマンドをチェーンする必要があります。他のオプションは、将来ビルドが失敗するためです。

したがって、必要なのはレイヤーを減らすことの副作用であり、レイヤーを減らすために必ずしもレイヤーを減らすわけではありません。

8
BMitch