本記事は
AWSアワード受賞者祭り
7日目の記事です。
✨🏆
6日目
▶▶ 本記事 ▶▶
8日目
🏆✨

ドーモ、浮田です。 昼食に素うどんばかり食べていたので、上司に心配されていました。 最近は釜玉うどんにバージョンアップしたので、上司も安心することでしょう。
はじめに
こんなことができるんだよ〜という記事です。
コンテナのベストプラクティスの一つに、不要なパッケージをインストールしない*1ことが挙げられています。 これは、不要なパッケージをインストールしないことで依存関係を減らしイメージサイズを減らすためです。 今回は、依存関係に着目しAmazon Linux 2023(以下、AL2023)から依存関係を最小限に抑えたコンテナを作成します。 ベースコンテナには、AWSが提供しているAL2023ベースコンテナイメージを使います。
コンテナイメージを小さくすることのメリット
コンテナイメージを小さくすることのメリットを以下に記載します。
- セキュリティの向上
不要なパッケージを含めないことで、脆弱性が減少し攻撃対象領域が小さくなる。
- コストの削減
ECRのストレージコストやネットワーク転送コストを削減できる。
- スケーラビリティの向上
ECRからイメージをプルする時間やコンテナの起動時間を短縮することで、素早くスケーリングできトラフィックの急増に対応できる。
Amazon Linux 2023を使うメリット
AWSによる長期的なサポートとパッケージバージョンの固定化*2による運用のしやすさがメリットになります。 AL2023は、リポジトリがバージョニングされており、パッケージのバージョンが固定化されている*3ため、手元でパッケージのバージョン管理を意識することなく開発を進められます。
GitHubのDependabotでベースイメージのバージョンを自動的に更新することができるので、例えば、AL2023のリリースタグが2023.6から2023.7になるとGitHubでPRを作成するなどの運用が可能です。
また、AL2023はAWSからリリースノートが提供*4されており、どのパッケージに更新があるか分かりやすいです。
コンテナイメージの作成
bashのみをインストールしたコンテナイメージを作成します。
イメージの作成には、マルチステージビルドを活用します。 最初のステージでは、dnfのinstallrootオプションでパッケージのインストール場所を指定し、bashをインストールします。 bashをインストールしたディレクトリを次のステージの/ディレクトリにコピーすることで、依存関係を最小限に抑えたコンテナイメージを作成することができます。
dockerfileの解説
buildステージで/installrootディレクトリを作成します。
dnfのinstallrootオプションでパッケージのインストール先に/installrootを指定します。
releaseverオプションでパッケージリポジトリのバージョンを指定します。
rpm -q system-releaseを叩くとsystem-release-2023.8.20250707-0.amzn2023.noarchのような結果を得られるので、そこからqueryformatオプションでバージョンのみを抜き出しています。
setopt=install_weak_deps=Falseオプションで依存関係が弱いパッケージのインストールをスキップします。
これで、依存関係を最小限に抑えたbashを/installrootディレクトリにインストールすることができます。
buildステージの/installrootディレクトリをscratch*5ステージの/ディレクトリにコピーし、コンテナ起動時にbashを起動するようにしたら完成です。
FROM public.ecr.aws/amazonlinux/amazonlinux:2023 AS build
RUN mkdir /installroot
RUN dnf -y \
--installroot /installroot \
--releasever=$(rpm -q system-release --queryformat '%{VERSION}') \
--setopt=install_weak_deps=False \
install bash \
&& dnf --installroot /installroot clean all
FROM scratch AS scratch
COPY --from=build /installroot /
ENTRYPOINT ["bash"]
ビルド結果
ビルドすると26.1MBとかなり小さなイメージができました。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE amazonlinux 2023-bash 580da8cc865e 27 minutes ago 26.1MB public.ecr.aws/amazonlinux/amazonlinux 2023 aab732c9dab9 7 days ago 182MB public.ecr.aws/amazonlinux/amazonlinux 2023-minimal 39004e0140fb 7 days ago 120MB debian latest 49c8d736314a 2 weeks ago 139MB fedora latest 999a110c3d3c 3 weeks ago 174MB nginx latest 889e2cc329c8 3 weeks ago 198MB ubuntu latest 70ed52c84b4e 3 weeks ago 101MB
実際に起動してみると、lsやdnfコマンドすらないですね。
$ docker run -it --rm amazonlinux:2023-bash bash-5.2# echo /sbin/* /sbin/iconvconfig /sbin/ldconfig /sbin/zic bash-5.2# echo /bin/* /bin/alias /bin/bash /bin/bashbug /bin/bashbug-64 /bin/bg /bin/catchsegv /bin/cd /bin/command /bin/fc /bin/fg /bin/gencat /bin/getconf /bin/getent /bin/getopts /bin/hash /bin/iconv /bin/jobs /bin/ld.so /bin/ldd /bin/locale /bin/localedef /bin/pldd /bin/read /bin/sh /bin/sotruss /bin/sprof /bin/type /bin/tzselect /bin/ulimit /bin/umask /bin/unalias /bin/wait /bin/zdump
比較として、AL2023のコマンド一覧を載せておきます。
$ docker run -it --rm public.ecr.aws/amazonlinux/amazonlinux:2023 bash-5.2# ls /sbin/ alternatives chroot getpcaps ldconfig update-alternatives capsh getcap iconvconfig setcap zic bash-5.2# ls /bin/ '[' dnf-3 id pydoc3 sync alias du install pydoc3.9 tac arch echo jobs python3 tail awk egrep join python3.9 tee b2sum env ld.so read test base32 expand ldd readlink timeout base64 expr link realpath touch basename factor ln rm tr basenc false locale rmdir true bash fc localedef rpm truncate bashbug fg logname rpm2archive trust bashbug-64 fgrep ls rpm2cpio tsort bg fmt md5sum rpmdb tty ca-legacy fold mkdir rpmkeys type cat gapplication mkfifo rpmquery tzselect catchsegv gawk mknod rpmverify ulimit cd gdbus mktemp runcon umask chcon gencat modulemd-validator sed unalias chgrp getconf mv seq uname chmod getent nice sh unexpand chown getopts nl sha1sum uniq cksum gio nohup sha224sum unlink comm gio-querymodules-64 nproc sha256sum update-ca-trust command glib-compile-schemas numfmt sha384sum users coreutils gpg od sha512sum vdir cp gpg-error p11-kit shred wait csplit gpg2 paste shuf wc curl gpgme-json pathchk sleep wcurl cut gpgv2 pinky sort who date grep pldd sotruss whoami dd groups pr split xmlcatalog df gsettings printenv sprof xmllint dir hash printf stat xmlwf dircolors head ptx stdbuf yes dirname hostid pwd stty yum dnf iconv pydoc sum zdump
おわりに
今回は、依存関係を最小限に抑えたAL2023のコンテナイメージを作成しました。 コンテナイメージを小さくすることで、セキュリティの向上やイメージをプルする時間が短縮されたことによるスケーラビリティの向上、ECRのストレージコストの削減など、多くのメリットがあります。 AL2023をもっと軽量にしたいけれど、言語の都合によりdistrolessを使いづらい...みたいな場合に、活用してみるのはありかもしれません。
参考) Building bare-bones AL2023 container images, https://docs.aws.amazon.com/linux/al2023/ug/barebones-containers.html
*1:https://docs.docker.com/build/building/best-practices/#dont-install-unnecessary-packages
*2:https://docs.aws.amazon.com/ja_jp/linux/al2023/ug/deterministic-upgrades.html
*3:https://aws.amazon.com/jp/blogs/news/amazon-linux-2023-a-cloud-optimized-linux-distribution-with-long-term-support/
*4:https://docs.aws.amazon.com/ja_jp/linux/al2023/release-notes/relnotes.html
*5:https://docs.docker.com/build/building/base-images/#create-a-base-image