[解決済み】Dockerfileの複数RUNと1つの連鎖RUN、どっちがいい?
質問
Dockerfile.1
は、複数の
RUN
:
FROM busybox
RUN echo This is the A > a
RUN echo This is the B > b
RUN echo This is the C > c
Dockerfile.2
が加わる。
FROM busybox
RUN echo This is the A > a &&\
echo This is the B > b &&\
echo This is the C > c
各
RUN
はレイヤーを作成するので、レイヤーは少ない方がいいとずっと思っていて、そのため
Dockerfile.2
が良いですね。
の場合、当然そうなります。
RUN
が追加したものを削除します。
RUN
(例)
yum install nano && yum clean all
) が、すべての
RUN
を追加する場合、いくつか考慮しなければならない点があります。
-
レイヤーは前のレイヤーの上に差分を追加するだけなので、後のレイヤーが前のレイヤーで追加されたものを削除しない場合、どちらの方法でもディスクスペースを節約する利点はあまりないはずです。
-
レイヤーはDocker Hubから並列に引き出されるため
Dockerfile.1
の方が若干大きいかもしれませんが、理論的にはダウンロードが速くなります。 -
もし、第4文を追加する場合(つまり
echo This is the D > d
) とローカルに再構築します。Dockerfile.1
はキャッシュのおかげでビルドが速くなりますがDockerfile.2
を実行すると、4つのコマンドをすべて再実行しなければなりません。
では、質問です。 Dockerfileを行うにはどちらが良いのでしょうか?
どのように解決するのですか?
可能な限り、私はいつもファイルを作成するコマンドと同じファイルを削除するコマンドをマージして、1つの
RUN
という行があります。これは、各
RUN
の行は画像にレイヤーを追加し、出力は文字通りファイルシステムの変更であり、それを
docker diff
を一時的なコンテナ上に作成します。別のレイヤーで作成されたファイルを削除しても、ユニオンファイルシステムが行うのは新しいレイヤーでのファイルシステムの変更を登録するだけで、ファイルはまだ前のレイヤーに存在し、ネットワーク経由で配送されてディスクに保存されます。ですから、ソースコードをダウンロードし、それを展開し、バイナリにコンパイルし、最後にtgzファイルとソースファイルを削除する場合、画像サイズを小さくするために、本当はこれをすべて1つのレイヤーで行いたいのです。
次に、個人的には、他の画像で再利用できる可能性と予想されるキャッシュ使用量に基づいてレイヤーを分割しています。4 つのイメージがあり、そのすべてが同じベースイメージ (例: debian) である場合、それらのイメージのほとんどに共通するユーティリティのコレクションを最初の実行コマンドに引っ張ってきて、他のイメージがキャッシュの恩恵を受けられるようにすることがあります。
イメージキャッシュの再利用を検討する際には、Dockerfileの順序が重要です。私は、ごく稀にしか更新されないコンポーネント、おそらくベースイメージが更新されたときだけ更新されるコンポーネントを調べ、それらをDockerfileの上の方に配置します。例えば、ホスト固有のUIDを持つユーザの追加や、フォルダの作成とパーミッションの変更などです。もしコンテナが、活発に開発されている解釈コード(JavaScriptなど)を含んでいる場合は、できるだけ遅く追加して、再構築がその単一の変更だけを実行するようにします。
これらの変更の各グループにおいて、できる限りレイヤーを少なくするように統合しています。たとえば、4つの異なるソースコードフォルダーがあったとしても、それらをひとつのフォルダーに収め、ひとつのコマンドで追加できるようにしています。apt-get などからインストールしたパッケージは、可能な限り単一の RUN にマージして、パッケージマネージャのオーバーヘッド(更新とクリーンアップ)の量を最小限に抑えられるようにしています。
多段ビルドに対応したアップデートを行いました。
私は、多段ビルドの最終段階でない段階での画像サイズの縮小については、あまり心配していません。これらのステージがタグ付けされて他のノードに出荷されない場合、各コマンドを別々の
RUN
という行があります。
しかし、ステージ間でコピーするのはファイルだけで、環境変数の設定やエントリポイント、コマンドといった画像の残りのメタデータはコピーされないため、レイヤーをつぶすための完璧な解決策とは言えません。また、Linuxディストリビューションでパッケージをインストールする場合、ライブラリやその他の依存関係がファイルシステム全体に散らばっていることがあり、すべての依存関係をコピーすることが困難になっています。
このため、私はCI/CDサーバでバイナリをビルドする代わりに多段ビルドを使用しており、CI/CDサーバには、以下のツールを実行するためだけに必要です。
docker build
jdk、nodejs、go、その他のコンパイルツールはインストールされていません。
関連
-
[解決済み] Dockerfileを使って複数のファイルを1階層でコピーするには?
-
[解決済み] Dockerのインストールができない : Docker Desktopの実行にはWindows 10 ProまたはEnterpriseバージョン15063が必要です
-
[解決済み] docker-compose v3.1でsecret値をどのように管理するのですか?
-
[解決済み] Docker Composeでコンテナにファイルをコピーする
-
[解決済み] DockerfileのRUNとCMDの違いについて
-
[解決済み】Docker.NETの不具合を修正する方法。パーミッションが拒否される問題
-
[解決済み】Dockerのイメージを削除する方法を教えてください。
-
[解決済み】Dockerfileを1つのコマンドでビルドして実行する。
-
[解決済み] standard_init_linux.go:190: exec user process caused "no such file or directory" - Docker
-
[解決済み] Dockerfileでスクリプトを実行する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Dockerのインストールができない : Docker Desktopの実行にはWindows 10 ProまたはEnterpriseバージョン15063が必要です
-
[解決済み] OOM例外がない場合、Docker-composeの終了コードは137になる
-
[解決済み] Dockerのバージョンを判断する方法 [重複]について
-
[解決済み】docker-composeで単一のコンテナを再起動する方法
-
[解決済み】終了したDockerコンテナを継続する方法
-
[解決済み】Dockerでディレクトリを変更するコマンドは?
-
[解決済み】特定のコンテナのみdocker-composeを立ち上げる。
-
[解決済み】Dockerイメージのビルドコンテキストが非常に大きい
-
[解決済み】Dockerのコンテナイメージが大きいのはなぜですか?
-
[解決済み】https://index.docker.io に接続しようとすると、ネットワークがタイムアウトしました。