Dockerfile に apt, apt-get, source コマンドを書く時のTips

この記事は Dockerfile を初めて書くときに役立ったtipsをまとめました。
apt, apt-get, source コマンドを中心に調べたことを挙げています。

公式の Dockerfile のベストプラクティスはこちら。また、こちらの @zembutsu 氏のスライドが大変助かりました。ありがとうございます。こちらで触れていない内容もありますので、ぜひご覧ください。

尚、下記内容の docker 実行イメージは Ubuntu 18.04を対象としています。 そのため Docker Desktop for Windows を利用する場合、Linux container に切り替える必要があります。

apt または apt-get を使うと警告が出る

apt を使う場合に出る警告

RUN apt install -y nyancat
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

CLI インターフェース向けではないということで注意は必要ですが、無視しても動きます。

apt-get を使う場合に出る警告

RUN apt-get install -y nyancat
debconf: delaying package configuration, since apt-utils is not installed

debconfig や apt-utils についての説明はこちらで確認できます。また、警告を非表示にすることも一応可能です。 こちらも無視しても動きます。

実際に使う場合は

docker 公式では apt-get が使われていますが、 現在 Debian では aptを推奨していること、今回下位互換性を意識する必要がないことから apt を用いましょう。

実際は下記のように --no-install-recommends オプションを使って必要最小限のインストールを一度に複数行うのがいいでしょう。また、apt updateapt installの行をまとめることで古いパッケージ情報のキャッシュ利用を避けることができます。最後に不要なパッケージマネージャーのキャッシュを削除して容量を削減します。 これらのコマンドをまとめることでレイヤ数を必要最小限にし、さらに容量を削減できます。

RUN apt update \
 && apt install -y --no-install-recommends \
    cowsay \
    nyancat \
 && apt -y clean \
 && rm -rf /var/lib/apt/lists/*

一連のコマンド後に && でさらにコマンドを連結することができますが、依存関係のあるライブラリのインストールや、ln コマンドによるシンボリックリンク作成など、無暗に連結するとエラーになるものがありますので注意してください。 最初はあまり連結せずにRUNで書いて動作を確認し、その後行末から連結して動作確認するのがおすすめです。 但し、状況によっては後述のマルチステージビルドの方法を検討しましょう。

source コマンドが使用できない

Ubuntu の /bin/sh は bash でなく Dash が使われており、Dash には source コマンドが無いためです。source の代わりに . を使用します。 尚、下記の例は相対パスで .bash_profile を指定していますが、絶対パスで指定するほうが無難でしょう。

RUN source .bash_profile  # 実行エラー
RUN . .bash_profile

ビルド環境と実行環境を分ける(マルチステージビルド)

複数のFROMASを使ってビルド環境と実行環境のイメージを分離すること ( マルチステージビルド ) で、実行環境のみを保存することによりイメージ容量を縮小できます。イメージ内でビルドしたライブラリを使う場合に有効です。
また、ビルド環境のレイヤ数やサイズは最終的に生成される実行環境のイメージに影響しないため && を極限まで使ってレイヤ数を減らす必要がなくなり、複雑さを低減できます。

FROM image_A AS build-native-env
# .. 開発環境で特定ライブラリ, 実行プログラムをビルド ..

FROM image_B
COPY --from=build-native-env /projectdir
# image_A でビルドしたデータをコピーして実行環境イメージを作成

あとがき

cowsayをインストールしたはずなのにコマンドが見つかりませんとなり、 which cowsay でバイナリの場所が表示されないのは何故なのか..
以上、Buzy の「鯨」を聴きつつお送りしました。

%d人のブロガーが「いいね」をつけました。