0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java アプリケーションを Distroless で動かす

0
Posted at

Java アプリケーションの Docker イメージサイズは重い

シンプルな Java アプリケーションの Dockerfile はこのようになっているのではないでしょうか?

# syntax=docker/dockerfile:1

FROM amazoncorretto:21.0.9-al2023
WORKDIR /deployments
ARG JAR_FILE=build/libs/distroless.jar
COPY ${JAR_FILE} app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

これだと、非常に重いイメージになってしまいます。
amazoncorretto:21.0.9-al2023 のサイズが 213.79 MB なので、このイメージはそこに fat jar の重さが加わります。

Docker イメージが重いと push, pull に時間がかかり、開発者体験の悪化に繋がります。
そこで、軽量なベースイメージを使用することで、イメージの軽量化を行います。

なぜ Distroless なのか

軽量なベースイメージとして、以下が挙げられます。

  • Alpine
  • Debian-slim
  • Distroless

Alpine は軽量なベースイメージとしてよく名前を聞き、amazoncorretto のイメージとしても Alpine ベースの物が提供されています。
サイズは 157.71 MB で、先ほどの al2023 ベースの物よりは軽量です。
しかし、C 言語のライブラリである glibc を使用していないことからトラブルがあると聞くので、私は使用したことがありません。(参考)

Debian-slim は Debian ベースなので glibc による問題はありません。
しかし、amazoncorretto から Debian-slim がベースとなったイメージの提供はないため、Debian-slim に JVM を載せる必要があります。
もしかしたら、amazoncorretto 以外のイメージだと Debian-slim ベースのものがあるかもしれません。

Distroless は、Debian ベースのイメージでありながら、shell を含んでいないためさらに軽量です。
Java 用のイメージも提供されています。

私は軽量なイメージが好きなので、Debian-slim よりも軽量な Alpine, Distroless。
Alpine よりもトラブルが少なそうな Distroless を使いたいと思いました。

Distroless の Java 用イメージ

Java や Debian のバージョンによって何種類かあるのですが、大まかに 2 種類あります。

  • JVM が入っているイメージ
  • JVM が動く環境があるイメージ

詳細や使い方は Distroless の Readme にありますが、2 種類のイメージの使用例を紹介します。

JVM が入っている Distroless

# syntax=docker/dockerfile:1

FROM gcr.io/distroless/java21-debian12:nonroot
WORKDIR /deployments
ARG JAR_FILE=build/libs/distroless.jar
COPY --chown=nonroot:nonroot ${JAR_FILE} app.jar

CMD ["app.jar"]

Readme にある通り、ベースの ENTRYPOINT に java -jar が指定されているので、CMD で fat jar を指定すれば動きます。

JVM が動く環境がある Distroless

# syntax=docker/dockerfile:1

FROM amazoncorretto:21.0.9-al2023 AS build
WORKDIR /jlink
RUN jlink \
    --verbose \
    --compress=2 \
    --strip-java-debug-attributes \
    --no-header-files \
    --no-man-pages \
    --add-modules java.base,java.desktop,java.instrument,java.logging,java.management,java.naming,jdk.jfr,jdk.unsupported \
    --output jre-min

FROM gcr.io/distroless/java-base-debian12:nonroot
WORKDIR /deployments
COPY --from=build --chown=nonroot:nonroot /jlink/jre-min /opt/jre-min
ENV JAVA_HOME=/opt/jre-min
ENV PATH=$JAVA_HOME/bin:$PATH
ARG JAR_FILE=build/libs/distroless.jar
COPY ${JAR_FILE} app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

JVM が動く環境はあるが、JVM は入っていないイメージです。
そのため、アプリケーションを動かすための最小限の JVM を構成することで、さらにイメージの軽量化が可能です。
この例では、マルチステージビルドを使用して、amazoncorretto から最小限のモジュールを含んだ JRE を作成し、Distroless にコピーしています。

3 つのイメージの重さ比較

M4 Mac でのビルドで arm64 プラットフォームになるため、amd64 よりはイメージが重くなっています。

amazoncorretto Distroless Distroless-base
811 MB 312 MB 200 MB

まとめ

Distroless とマルチステージビルドによるカスタム JRE を使用することで、JVM 提供のイメージよりも 1/4 軽量なイメージを作成することができます。
イメージサイズを小さくすることで、開発者体験を良くしましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?