Dockerfileのapt-getでよく見るあの呪文について
apt-getの呪文
Dockerfile内でapt-getを使ってアプリケーションをインストーするするとき以下のようなものをよく見ると思います。
RUN apt-get update && apt-get install -y \ xxx \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
公式ドキュメントによればこれらはDockerのイメージサイズを小さくする効果があるようです。 今回はこれを紐解いて行こうと思います。
比較
疑問が多いのは以下の部分だと思います。
apt-get clean
rm -rf /var/lib/apt/lists/*
これらをそれぞれない状態にしてイメージサイズを比較してみます。 今回はUbuntu:22.04をもとにNginxをインストールします。
イメージサイズ | |
---|---|
全部あり | 136.72MB |
apt-get cleanだけ実行 | 176.54MB |
rm -rf /var/lib/apt/lists/*だけ実行 | 136.72MB |
両方なし | 176.54MB |
確かに、全部ありはイメージサイズが小さいです。
rm -rf /var/lib/apt/lists/*
も同じ値になっています。
apt-get clean
だけを行ったものは両方ない場合と同じになっています。
それぞれのコマンドの意味を見ていきます。
apt-get clean
apt-get clean
はaptがダウンロードしてきたDebianパッケージファイルを削除するためのコマンドです。
ダウンロードされてきたファイルは/var/cache/apt
以下に一時的に保存され、再度インストールする際はダウンロードせずこちらが使用されます。
ではなぜこのコマンドはイメージサイズに影響を与えなかったのでしょうか?
この秘密は/etc/apt/apt.conf.d/docker-clean
にあります。
ここにはaptの設定が書いてあり、内容は以下のとおりです。
DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";
ここでaptの設定を行っており、インストール後に自動的にapt-get clean
相当の処理が走るようになっています。
つまりは、RUN命令に含めなくとも自動でダウンロードしたパッケージを削除してくれるということです。
UbuntuやDebianの公式イメージではこの設定がすでに行われています。
FROM ubuntu:22.04 RUN rm /etc/apt/apt.conf.d/docker-clean RUN apt-get update && apt-get install -y \ nginx
実際上記のようなDockerfileを作成しイメージをビルドするとイメージサイズは275.04MBととなります。
/# ls -la /var/cache/apt/archives | head total 17224 drwxr-xr-x. 1 root root 4096 Dec 1 07:59 . drwxr-xr-x. 1 root root 65 Dec 1 07:59 .. -rw-r--r--. 1 root root 29096 Mar 24 2022 fontconfig-config_2.13.1-4.2ubuntu5_all.deb -rw-r--r--. 1 root root 1041300 Feb 22 2021 fonts-dejavu-core_2.37-2build1_all.deb -rw-r--r--. 1 root root 1070038 Mar 24 2022 iproute2_5.15.0-1ubuntu2_amd64.deb -rw-r--r--. 1 root root 22768 Mar 25 2022 libatm1_1%3a2.5.1-4build2_amd64.deb -rw-r--r--. 1 root root 139806 Jan 25 2022 libbpf0_1%3a0.5.0-1_amd64.deb -rw-r--r--. 1 root root 315164 Mar 24 2022 libbrotli1_1.0.9-2build6_amd64.deb -rw-r--r--. 1 root root 44760 Jan 25 2022 libbsd0_0.11.5-1_amd64.deb
実際/var/cache/apt/
以下に.deb
ファイルが残されています。
では、このapt-get clean
は不要でしょうか?
それは使用するイメージによります。
ダウンロードしたパッケージの自動クリーンが入っていないイメージを使用する場合はあったほうが良いでしょう。
rm -rf /var/lib/apt/lists/*
/var/lib/apt/lists
以下を削除していますがここには何が入っているのでしょうか?
ここにはapt-get update
で取得したリポジトリのパッケージのリストが保存されています。
/# du -sh /var/lib/apt/lists 39M /var/lib/apt/lists # ls -al /var/lib/apt/lists/ | head total 39024 drwxr-xr-x. 1 root root 4096 Dec 1 07:58 . drwxr-xr-x. 1 root root 42 Dec 1 07:59 .. -rw-r--r--. 1 root root 99847 Dec 1 07:02 archive.ubuntu.com_ubuntu_dists_jammy-backports_InRelease -rw-r--r--. 1 root root 4893 Aug 24 19:11 archive.ubuntu.com_ubuntu_dists_jammy-backports_main_binary-amd64_Packages.lz4 -rw-r--r--. 1 root root 11115 Nov 30 16:18 archive.ubuntu.com_ubuntu_dists_jammy-backports_universe_binary-amd64_Packages.lz4 -rw-r--r--. 1 root root 114016 Dec 1 07:02 archive.ubuntu.com_ubuntu_dists_jammy-updates_InRelease -rw-r--r--. 1 root root 1566039 Dec 1 02:50 archive.ubuntu.com_ubuntu_dists_jammy-updates_main_binary-amd64_Packages.lz4 -rw-r--r--. 1 root root 12559 Nov 18 01:25 archive.ubuntu.com_ubuntu_dists_jammy-updates_multiverse_binary-amd64_Packages.lz4 -rw-r--r--. 1 root root 1024871 Dec 1 01:17 archive.ubuntu.com_ubuntu_dists_jammy-updates_restricted_binary-amd64_Packages.lz4
このディレクトリだけで39MBもあるので削除しておいたほうが無難でしょう。
問題としてはDockerfilen内で複数回apt-update
を走らせるたびに毎回取得が入ってしまいます。
ですが、よほど高速にビルドしたいという局面以外は毎回削除することが安全だと思っています。
最後に
Dockerにおけるapt-getの利用方法としてよく練られたコマンドだと思いました。
DebianやUbuntuの公式イメージは自動でapt-get clean
してくれるのでありがたいですね。
付録
以下に今回使用したDockerファイルを載せておきます。
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y \ nginx \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y \ nginx \ && apt-get clean
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y \ nginx \ && rm -rf /var/lib/apt/lists/*
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y \ nginx