SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

イベントレポート

新環境に適応して変化し続けるJava、Dockerコンテナ対応やマイクロサービスをサポートするプロジェクトなど【Oracle Code One 2018】

DockerとJava

 今年のCode Oneでは、コンテナ技術であるDockerに関するセッションは40件もあり、コンテナ技術に関する関心が高まっていることが伺えます。コンテナはLinuxカーネルの機能などを利用してOSの各種リソースを分離することで、他プロセスなどから独立/分離したアプリケーション実行環境を構築する技術で、特にDockerが有名です。ここでは、JavaをDockerコンテナで動かす際のノウハウに関するセッションを紹介します。

 Javaのコンテナ対応はJava 8から取り組まれていますが、Java 10になってコンテナ対応機能が拡充しました。Java 10よりも前のバージョンでは不具合があり注意が必要です。この不具合についてはAndreas Hochleitner氏のセッション(JVM CPU and Memory Settings for Docker Containers in Production [DEV6060])の内容を紹介します。

 Java 8(u121以前)では、JVM(Java Virtual Machine)がコンテナ環境に割り振られたCPUやメモリなどのリソース設定を無視し、コンテナのホスト環境のリソース情報を読み込んでしまう不具合があります。Javaは実行環境のCPUやメモリなどのリソース情報をもとにガベージコレクタやJVMに関する各種パラメータを自動で設定します。コンテナで動作するJavaがホスト環境のリソース情報をもとにパラメータ設定を行ってしまうことで、コンテナに割り振られている以上のCPUやメモリなどのリソースを使用しクラッシュしてしまうことがあります。この不具合は改善されてきたものの、Java 9以前ではコンテナ対応自体が試験的な導入に留まっています。Java 10でコンテナ対応機能が拡充し、コンテナのリソース割り振りに則した各種パラメータを設定できるようになりました。そのため、DockerでJavaを動作させる場合、Java 10以降の新しいバージョンのJDK(Java Development Kit)の使用が推奨されています。

 一般にコンテナイメージのサイズはより小さくなることが望ましいとされています。Java実行環境を含むコンテナイメージ作成については、OracleのMikael Vidstedt氏とBob Vandette氏のセッションの内容(Java in a World of Containers [DEV6100])を紹介します。

 このセッションでは、コンテナイメージを小さくするための3点のテクニックについて紹介されています。

  • Java実行環境のサイズ削減
  • クラスメタデータの共有化
  • Dockerリソース制限

Java実行環境のサイズ削減(Java 9以降)

 Java開発環境(JDK: Java Development Kit)11のサイズは300MBほどあり、そのままで使用するにはサイズが大きすぎます。この中にはアプリケーションが使用しないモジュールが含まれています。そこで、これらの不必要なモジュールを取り除き、アプリケーションに必要なモジュールだけを残したサイズの小さなJava実行環境(JRE: Java Runtime Environment)を作成します。このサイズの小さなJREを作成するためには、JDK 9で追加されたjlinkを使用します。jlinkは指定したJavaモジュールのみをまとめたカスタムJREを作成するツールです。

 図1はカスタムJREを作成し、java -versionコマンドを実行するDockerfileの例です。この例では、空行で区切られた前半部分でカスタムJREを作成し、後半部分でカスタムJREを使用してjava -versionコマンドを実行します。特に注目すべきは5行目の下線を引いた箇所です。jlinkコマンドを使用してJavaの最小セットであるjava.baseモジュールを指定したカスタムJRE(my-jre)を作成しています。例のようにjava.baseのみであれば50MB程度まで小さくすることができます。

図1 カスタムJREを作成し、java -versionコマンドを実行するDockerfile例
FROM oraclelinux:latest AS java-build
ADD openjdk-11+28_linux-x64_bin.tar.gz /opt/jdk
ENV PATH=/opt/jdk/jdk-11/bin:$PATH
WORKDIR /jlink
RUN jlink --output my-jre --add-module java.base

FROM oralcelinux:latest
COPY --from=java-build /jlink/my-jre /opt/my-jre
ENV PATH=/opt/my-jre/bin:$PATH
CMD ["java", "-version"]

クラスメタデータの共有化(Java 10以降)

 一般にコンテナを使用する場合、同じ処理を行う複数のコンテナを並列で同時に動作させるケースが考えられます。その場合、JVMごとに同じクラスメタデータを重複してロードすることになります。Application Class Data Sharing(App CDS)を使用することで、この無駄を解消できます。App CDSは図2の様に、JavaクラスメタデータをJVM間で共有する機能です。事前にクラスメタデータを含むアーカイブファイルを作成し、JVM起動時にメモリマッピングして読み込ませることができます。一からクラスをロードするよりも早くロードすることができ、起動時間短縮にもつながります。

図2 Application Class Data Sharing
図2 Application Class Data Sharing

Dockerリソース制限(Java 10以降)

 コンテナごとに必要な量だけのCPUとメモリリソースを割り当てることも重要です。前述したようにJava 10からであればDockerのリソース制限設定がそのままJavaにも適用されます。DockerのCPUオプションはJVMのワーカスレッド数に、メモリオプションはJavaヒープなどの最大適用可能サイズを制限します。

 セッションでは他にも試験的な機能として、Project PortolaAlpine Linuxとlibc実装のmuslを使用した軽量イメージ)、Ahead-of-Time Compilation(事前コンパイルされたコードのコンテナ間共有)、 SubstrateVMGraalVM上で動作する高速起動、低イメージサイズ、低メモリ消費のネイティブイメージの作成)が紹介されていました。

 JavaのDockerコンテナ対応はJava 10で実用の段階を迎え、マイクロサービスやサーバレス技術とも相まって今後も目が離せない状況が続きそうです。

次のページ
Microserviceのためのライブラリ、仕様、VM:helidon, microprofile, graalvm

この記事は参考になりましたか?

イベントレポート連載記事一覧

もっと読む

この記事の著者

Oracle Code One 2018レポートチーム(Oracle Code One 2018レポートチーム)

坂本 統(NTTコムウェア)、二ノ方 一生(NTTデータ)、髙雄 慎二(NTT)

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11243 2018/12/06 13:59

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー