DockerfileのRUN命令には、--mount
というオプションがあります
https://docs.docker.com/reference/dockerfile/#run---mount
このオプションで指定したディレクトリで行った作業は、最終的なコンテナイメージには反映されません
また、このディレクトリはマルチステージビルド時にコンテナ間で共有することも可能です
この記事では、--mount
オプションを利用してこのようなリソースを、最終的なコンテナのイメージサイズに反映させないようにする方法を紹介します
- aptなどパッケージマネージャーのキャッシュ
- ビルドに必要で、実行時には不要なソースコードやファイル
- gitやwgetなどの、ファイルダウンロード用のパッケージ
1. aptなどパッケージマネージャのサイズ削減
ドキュメントに載っている例となりますが、実際にどのくらいの削減を見込めるのか、見てみます
https://docs.docker.com/reference/dockerfile/#run---mounttypecache
ベースイメージ
今回はubuntu 24.04で検証します
容量は136MBです
$ docker image ls ubuntu:24.04
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 24.04 3f85b7caad41 4 weeks ago 136MB
apt update
パッケージを更新するだけでどのくらいサイズが増えるか確認します
FROM ubuntu:24.04
RUN apt-get update
$ docker build -t dockerfile-run-mount:apt .
$ docker image ls dockerfile-run-mount:apt
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerfile-run-mount apt 8b9733505c07 3 hours ago 197MB
61MB増加の197MBでした
パッケージをインストール
make
をインストールしてみます
FROM ubuntu:24.04
RUN apt-get update && apt-get install --no-install-recommends -y make
$ docker build -t dockerfile-run-mount:make .
$ docker image ls dockerfile-run-mount:make
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerfile-run-mount make 6b118565e1b4 2 hours ago 198MB
make
をインストールすると1MB増えました
cacheを使用してパッケージをインストール
公式ドキュメントの通り、RUN命令にオプションを追加します
FROM ubuntu:24.04
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install --no-install-recommends -y make
二つのディレクトリに対して、オプションが設定されています
/var/cache/apt
/var/lib/apt
オプション内容は同一です
--mount=type=cache,target={ディレクトリ名},sharing=locked
-
target={ディレクトリ名}
マウント先ディレクトを指定します
このディレクトリに対して行った作業は、コンテナイメージ内に残りません -
sharing=locked
複数の命令から書き込みできないようにする設定です
今回はapt用のキャッシュは他では使用しないですが、マルチステージビルド内でキャッシュを共有する場合には設定が必要になります
この状態でコンテナをビルドします
$ docker build -t dockerfile-run-mount:cache .
$ docker image ls dockerfile-run-mount:cache
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerfile-run-mount cache ad9befef2bfd 2 hours ago 137MB
ビルド後のサイズは137MBと、ubuntu:24.04からmake
分の1MB増えただけです
cacheオプションの効果で、apt update
の分だけサイズ削減できました
2. ソースコードからビルドする際のサイズ削減
コンテナ内で使うライブラリを、ソースコードからビルドしないといけないケースでの活用例です
モダンなプログラミング言語のライブラリであれば気にしなくていいですが、makeのプロジェクトではサイズ削減が見込める手法です
※必要なパッケージが足りていないので、下記のコードではopensslはビルドできません
FROM ubuntu:24.04 as src
WORKDIR /usr/local/src
RUN apt-get update && apt-get install --no-install-recommends -y git
RUN git clone --depth 1 https://github.com/openssl/openssl.git
FROM ubuntu:24.04
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install --no-install-recommends -y \
make
RUN --mount=type=cache,target=/usr/local/src,from=src,source=/usr/local/src cd /usr/local/src/openssl \
&& ./Configure \
&& make \
&& make install
マルチステージビルドを使用し、二つの点でサイズ削減を行なっています
ソースコードフォルダ自体を、本番コンテナから分離する
--mount
オプションの--type=cache
では、マルチステージビルドの別コンテナからディレクトリをマウントすることが可能です
上記のDockerfileでは、ソースコード用のコンテナを実行用コンテナとは別に用意し、ソースコードはそちらに展開するようにしています
--mount=type=cache,target=/usr/local/src,from=src,source=/usr/local/src
これにより、実行用コンテナにソースコードをコピーすることなく、実行用コンテナ内でビルドが可能です
ソースコードを取得するためのパッケージ
gitやwgetなど、ソースコードをコンテナ内に持ってくるためのコマンドは、実行用のコンテナ内では不要なことが多いと思います
マルチステージビルドで、ソースコードを取得するためのコンテナを別で定義し、実行用コンテナではソースコードはマウントするのみとしています
FROM ubuntu:24.04 as src
WORKDIR /usr/local/src
RUN apt-get update && apt-get install --no-install-recommends -y git
RUN git clone --depth 1 https://github.com/openssl/openssl.git
FROM ubuntu:24.04
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install --no-install-recommends -y \
make
RUN --mount=type=cache,target=/usr/local/src,from=src,source=/usr/local/src cd /usr/local/src/openssl \
&& ./Configure \
&& make \
&& make install
まとめ
コンテナのイメージサイズを削減する手段として、RUN命令の--mount
オプションを紹介しました
今回マウントタイプはcache
のみ例示しましたが、他にはtmpfs
も有用です
https://docs.docker.com/reference/dockerfile/#run---mounttypetmpfs
dockerコンテナはその仕組み上、一度ダウンロードしたソースコードを以降のRUN命令で削除しても、最終的なイメージサイズの削減にはなりません
実行用のコンテナにいかに不要ファイルを入れないかが重要です