必要最小限にまで小さくする際に試したことをまとめました。当時はまだなかったdockerイメージや、JDKの機能の違いにより、今ではちょっと古い部分もあります。今回の記事も、半年もしないうちに古くなると思うので、2019年9月時点での方法だと思って読んでいただけると幸いです。メットライフドームは埼玉県所沢市にあるドーム球場。本文には特に関係ありません。そもそも、そのメリットをネットで調べてみてもあまり明確な答えは見つかりません。実行環境のディスクを節約できる?Fargateはイメージのサイズの大小で料金が変わらないので小さくても安くはならない。EC2タイプならある程度は節約になるかも?ECRの転送料金が抑えられる?と言っても1GBあたり0.1USD程度なので気にしたところで効果は薄そう。最近のクラウドサービス上で運用するならあまり考えなくてもいい問題かもしれません。作ってしまったので以下で説明していきます。興味のある方はどうぞ。マルチステージビルドマルチステージビルドはDocker17.05から追加された機能で、前のステージのビルドでの成果物を次のステージのビルドにコピーできます。docs.docker.comよく例に上がるのはGoを使ったイメージです。Goはコンパイルしたバイナリがあれば、実行環境にGoのコンパイラやソースコードなどは不要です。アプリ用イメージは小さくシンプルになります。Goのシングルバイナリと似たような環境です。Goとは違い、jar単体だけあってもアプリケーションは起動できず、jarの起動のためにはJDKが必要です。350MB程度あります。365MBそのほとんどがJDKで占められています。必要なモジュールだけで構成されるJREを自分で作ることができます*1。コマンドは必要なモジュールを選んでJREを生成するコマンドです。含むJREの生成例です。335.3MBから50.2MBまで減りました。/tmp/jre-java-baseまた、いくつかサイズを削減に効きそうなオプションを足すともう少し小さくなります。コマンドはjarやclassファイル内で使われるモジュールの依存関係を解析します。java.loggingしかし、この2つだけを残したJREでは起動しません。それらのjarが使うモジュールが足りないのです。理由なく固定でモジュールが列挙されているか、それをそのまま持ってきているだけの方法しか見つかりませんでした。jarに含まれるjarも含めて依存関係を解析するスクリプトを用意しました。jarを展開して、アプリケーション本体とSpringBootの起動部分とjarの依存関係を調べます。${TMP_DIR}/BOOT-INF/lib/*.jarオプションについていくつか補足します。そのまま渡せる形式で出力します。場所を指定しています。このモジュールを使っているとこのオプションがないと通りません。--multi-relaseマルチリリースJAR*2に対してどのバージョンとして解析するかを指定しますこれで実行すると必要なモジュールが出力されます。12java.base,java.compiler,java.desktop,java.instrument,java.management.rmi,java.prefs,java.scripting,java.security.jgss,java.security.sasl,java.sql.rowset,jdk.attach,jdk.httpserver,jdk.jdi,jdk.unsupportedDockerfile以上をまとめてDockerfileにします。50MBくらいあるので、単純に作ると400MB程度になるはずです。JREをコピーします。/app/app.jarビルド結果。