📚

コンテナイメージのスリム化

2024/05/02に公開

Alpine使っておけばいいんじゃんと思ってました。お恥ずかしい限り。。。

いろいろあるようですが、いまさら知ったdistrolessについて。
以下の方々が詳しく書いてくれています。

https://blog.inductor.me/entry/alpine-not-recommended
https://blog.unasuke.com/2021/practical-distroless/
https://ceblog.mediba.jp/post/662840014480326656/コンテナイメージとしてdistrolessを使うべき理由って
https://zenn.dev/yoshii0110/articles/21ddb58c6f6bfa

以下は、Alpineだとなんで性能がでないの?のお話

https://superuser.com/questions/1219609/why-is-the-alpine-docker-image-over-50-slower-than-the-ubuntu-image

distroless イメージって?

シンプルに言えば、ひたすら不要なものを削ったイメージ。シェルも入ってない

Googleが提供しているイメージで以下に説明があります。

https://github.com/GoogleContainerTools/distroless

特徴は以下の通り

  • サイズが非常に小さい
  • 不必要なパッケージが入っていない -> セキュリティリスクの低減

提供されているイメージ

以下が提供されているイメージ。

https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#what-images-are-available

大きく3つに分かれてる模様。

  • static
  • base
  • 各言語用(Java, Node.js, Python、スタティックリンクでコンパイルされたバイナリ)

さらに、debug, non-rootなどもある

staticとbaseについて

以下に違いについて記載がありますが、一番軽いのはstatic。

https://github.com/GoogleContainerTools/distroless/blob/main/base/README.md

イメージ
static libcを必要としないスタティックリンクでコンパイルされたアプリケーション用
base-nossl staticイメージにglibcを加えたもの。ただしsslなし
base base-nosslイメージにSSL関連(libssl + OpenSSL)を加えたもの

コンテナのサイズは以下の通り結構違う。staticが約2MB、baseが20MBちょっと。
まぁ、それでも小さいが。

gcr.io/distroless/static-debian12   latest          92a33fd0eb30   N/A            1.99MB
gcr.io/distroless/base-debian12     latest          29fcbcf78574   N/A            20.7MB

ちなみにこの手の話で出てくるAlpine, Debian-slimは以下の通り。

debian                              stable-slim     16074b6b4d1e   7 days ago     74.8MB
alpine                              latest          05455a08881e   3 months ago   7.38MB

Microsoftが提供しているJavaのコンテナのサイズは以下の通り。DebianとUbuntu比較するのも微妙かもしれないが、、、

mcr.microsoft.com/openjdk/jdk       21-distroless   d280404937a7   16 hours ago   336MB
mcr.microsoft.com/openjdk/jdk       21-ubuntu       39a48f90db93   16 hours ago   460MB

130MBほど。そこそこ違う感じ。Googleも提供しているJava17で比較すると以下。

mcr.microsoft.com/openjdk/jdk       17-ubuntu       57581481553d   16 hours ago   432MB
mcr.microsoft.com/openjdk/jdk       17-distroless   1f653f5e48f7   16 hours ago   309MB
gcr.io/distroless/java17-debian12   latest          4c39497154b6   N/A            225MB

細かいところなんも見てないのでなんともだけど、サイズだけ見るとGoogleがダントツ。。

使うときの注意点

これもいかに記載ありますが

https://github.com/GoogleContainerTools/distroless/tree/main?tab=readme-ov-file#entrypoints

shellが入っていないので、ENTRYPOINTを書く場合は配列で。
配列にしないと、/bin/sh -c で実行されちゃうので。。。

補足

その1

Alpineだと性能が出ない話の補足。
性能が出ないのはAlpineがglibcじゃなくて、muslというlibcを使っているからとのこと。

上に書いたページでは、muslのほうが2m secばかり遅いからそれが何回も繰り返されるうちに大きな差になったんだろうと書いてある。

その2

スタティックリンクでコンパイルされたバイナリ
すごく大雑把に言うと実行に必要な全てのライブラリをバイナリに含めてしまうのがスタティックリンク

その反対?がダイナミックリンク。こちらはアプリケーション部分のみバイナリに含めライブラリなどは、含めず、実行時に呼び出すやり方。(Rubyとかでgem使うやりかたとほぼ同じ)

# ls -l
total 816
-rw-r--r-- 1 root root     58 May  2 00:54 a.c
-rwxr-xr-x 1 root root  16608 May  2 00:54 dynamic
-rwxr-xr-x 1 root root 809728 May  2 00:54 static

a.cをスタティックリンクとダイナミックリンクでコンパイルした結果。
staticのほうがやはりサイズはでかくなる。。。

lddコマンドでリンクしているファイルが見れるので見てみる。

# ldd dynamic
        linux-vdso.so.1 (0x00007ffde677f000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5c68c4a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5c68e2b000)

こんな感じで、使ってるほかのファイルが何かを見れる

# ldd static
        not a dynamic executable

ちなみにスタティックリンクなファイルにlddすると、上記のようになる。

個人的な見解

セキュアな点を織り込むとdistrolessになるけど、シェルがないとか使い勝手を考えるとdebian-slimのほうがよさげ

開発するときのベースはdebian-slim
Productionに入れる前の試験あたりからdistrolessに変えるとかかな。

まぁ、ちょっと使ってみてかな

Discussion