Java 8ランタイム・コンテナ・イメージの作成とデプロイ

Red Hat で Solution Architect として OpenJDK を担当している伊藤ちひろ(@chiroito)です。

この記事は、Red Hat Developerのブログ記事、Creating and deploying a Java 8 runtime container image | Red Hat Developer の翻訳記事です。


https://developers.redhat.com/sites/default/files/styles/article_feature/public/blog/2018/09/OpenJDK.png?itok=WQGGjnO3

Javaの実行環境はコンパイルされたソースコードを実行できるものでなければならないが、例えばOpenJDKのような開発キットには、ソースコードをコンパイルして実行するためのライブラリ/バイナリがすべて含まれている。基本的に、後者は実行環境の上位集合です。OpenJDKのサポートとライフサイクルに関する詳細はこちらをご覧ください。

Red Hat は、Java 8 と 11 の両方の OpenJDK を搭載したコンテナイメージを出荷し、サポートしています。詳細はこちらを参照してください。Red Hat Middleware を使用している場合、出荷された s2i イメージは、Red Hat Openshift Container Platform などにデプロイするのにも便利です。

Red HatはOpenJDKベースのJava 8と11のイメージしか提供していないことに注意してください。とはいえ、開発者が独自のJavaランタイムイメージを作成したい場合もあるでしょう。例えば、ランタイムイメージを実行するためにストレージを最小化するといった理由が考えられます。その一方で、JolokioやHawkularなどのライブラリや、セキュリティパラメータの設定など、多くの手作業が必要になります。そういった細かい作業をしたくない場合は、Red Hatが出荷しているOpenJDK用のコンテナイメージを使うことをお勧めします。

この記事では、以下のことを行います。

  • DockerとBuildahでイメージを構築します。
  • DockerとPodmanを使って、イメージをlocalhostで実行します。
  • イメージをQuayにプッシュします。
  • 最後に、OpenShiftにストリームをインポートしてアプリを実行します。

この記事は、OpenShift 3.11と4.0のベータ版の両方で書かれています。早速ですが、ご紹介します。

設定方法

私たちのイメージを使用し、その動作を確認するために、バンドルの一部としてWebアプリを使用します。最近、Microprofile.ioは、MicroProfile Starter betaを発表しました。これは、ダウンロード可能なパッケージを作成することで、MicroProfileの使用を開始するのに役立ちます。Microprofile.ioにアクセスして、MicroProfile with Thorntail V2のパッケージを入手してください。

https://developers.redhat.com/blog/wp-content/uploads/2019/02/screenshot3-300x256.png

ダウンロードボタンをクリックしてアーカイブファイルを取得します。

Red Hat Enterprise Linux(RHEL)のマシンでは、まず、demoappなどの一時ディレクトリを作成し、ダウンロードした成果物をそこに解凍します。

tempディレクトリで、次のように実行します:

$ mvn clean compile package

これで、ビルドされたデモアプリができあがり、fat jarができました。このjarを呼び出して、Thorntailを実行できます。

target/demo-thorntail.jar`をtempディレクトリにコピーしましょう。

ここでは、各レイヤーにコメントをつけたDockerfileを紹介します。このファイルのソースコードは、こちらのGitHubでもご覧いただけます。

# Java 8 ランタイムの例
# Red Hatの公式レジストリとベースイメージ
FROM registry.access.redhat.com/rhel7-minimal
USER root
# Javaランタイムのインストール
RUN microdnf --enablerepo=rhel-7-server-rpms \
install java-1.8.0-openjdk --nodocs ;\
microdnf clean all
# Javaがどこにあるかを明確にするためにJAVA_HOME変数を設定する
ENV JAVA_HOME /etc/alternatives/jre
# 自分のアプリのためのディレクトリ
RUN mkdir -p /app
# リッスンするポートを公開する
EXPOSE 8080
# MicroProfile starter appをコピーする
COPY demo-thorntail.jar /app/
# スクリプトをソースからコピー: run-java.shは、コンテナ内でコマンドラインからThorntailアプリを実行するための特定のパラメータを持っています。スクリプトの詳細は https://github.com/sshaaf/rhel7-jre-image/blob/master/run-java.sh にあります。
COPY run-java.sh /app/
# スクリプトを実行するためのパーミッションの設定
RUN chmod 755 /app/run-java.sh
# 最後に、スクリプトを実行する
CMD [ "/app/run-java.sh" ]

さて、Dockerfileの詳細がわかったところで、イメージの構築を進めていきましょう。

重要な点として、OpenJDKのJavaランタイムは「java-1.8.0-openjdk」としてパッケージされています。これには、-develパッケージに含まれているコンパイラやその他の開発ライブラリは含まれていません。

上記のDockerfileはRHELでビルドされています。つまり、ホストにはすでにサブスクリプションが添付されているので、subscription-managerに登録する必要はありません。

以下に、これを構築する2つの方法を紹介します。私のように RHEL を使用している場合は、2 つのバイナリのいずれかを選択してデプロイできます。両方とも rhel7-server-extras-rpms にあるはずです。

次のようにして extras リポジトリを有効にします。

# subscription-manager repos --enable rhel-7-server-extras-rpms

ローカルでイメージをビルドと実行

dockerでイメージを構築します。

$ docker build -t quay.io/sshaaf/rhel7-jre8-mpdemo:latest .

イメージを docker で実行し、localhost:8080 をコンテナのポート 8080 に指定します。

$ docker run -d -t -p 8080:8080 -i quay.io/sshaaf/rhel7-jre8-mpdemo:latest

また、buildahコマンドも使用できます。これは、作業中のコンテナから、Dockerfileから、またはスクラッチからコンテナイメージを作成するのに役立ちます。作成されたイメージはOCIに準拠しているので、OCIランタイム仕様を満たしたランタイム(DockerやCRI-Oなど)で動作します。

buildahでビルドします:

$ buildah bud -t rhel7-jre8-mpdemo .

buildahでコンテナを作ります:

$ buildah from rhel7-jre8-mpdemo

また、Podmanを使ってもコンテナを実行できます。これはBuildahSkopeoを補完するもので、Dockerのコマンドラインに似た体験を提供するものです。これにより、ユーザーはスタンドアロンの(オーケストレーションされていない)コンテナを実行できるようになります。また、Podmanはコンテナやポッドを実行するためのデーモンを必要としません。Podmanはextrasチャンネルの一部でもあり、以下のコマンドでコンテナを実行できます。

$ podman run -d -t -p 8080:8080 -i quay.io/sshaaf/rhel7-jre8-mpdemo:latest

Podmanの詳細については、Containers without daemons: Podman and Buildah available in RHEL 7.6 and RHEL 8 BetaおよびPodman and Buildah for Docker usersをご覧ください。

イメージができたので、それを OpenShift にデプロイしてアプリをテストしたいと思います。そのためには、ocクライアントライブラリが必要です。私は自分のクラスタを設定していますが、Red Hat Container Development Kit (CDK)/minishift、Red Hat OpenShift Online、または自分のクラスタも使用できます。手順は同じになるはずです。

OpenShiftにデプロイ

OpenShiftにデプロイするためには、以下のような構成が必要です。

  • 新しく作成したコンテナイメージのイメージストリーム
  • OpenShift用のデプロイメント構成
  • サービスとルーティングの設定

イメージストリーム

イメージストリームを作成するために、私のOpenShiftクラスタはどこかからコンテナイメージを引き出せるようにしなければなりません。これまで、イメージは私自身のマシンに存在していました。これを Quay にプッシュしてみましょう。Red Hat Quayのコンテナとアプリケーションのレジストリは、あらゆるインフラ上でコンテナの安全な保管、配布、デプロイを提供します。スタンドアロンのコンポーネントとしても、OpenShiftと組み合わせても利用可能です。

まずQuayにログインする必要がありますが、これは以下のように行います。

$ docker login -u="sshaaf" -p="XXXX" quay.io

そして、新しく作ったイメージをQuayにプッシュします:

$ docker push quay.io/sshaaf/rhel7-jre8-mpdemo

ここでは、デプロイする前の構成を見てみましょう。気になる方は、デプロイテンプレートの詳細を読み飛ばして、プロジェクトの作成に進んでください。

イメージができたので、ストリームを定義します。

- apiVersion: v1
kind: ImageStream
metadata:
name: rhel7-jre8-mpdemo
spec:
dockerImageRepository: quay.io/sshaaf/rhel7-jre8-mpdemo

上の例では、Quay.ioのイメージリポジトリに直接アクセスしています。

デプロイメントコンフィグ

次は、デプロイメント設定です。ここでは、ポッドやトリガーを設定し、新しく作成したストリームを指定するなどします。

コンテナやOpenShiftのデプロイメントに慣れていない方は、こちらの便利なebookをご覧になるとよいでしょう。

- apiVersion: v1
kind: DeploymentConfig
metadata:
name: rhel7-jre8-mpdemo
spec:
template:
metadata:
labels:
name: rhel7-jre8-mpdemo
spec:
containers:
- image: quay.io/sshaaf/rhel7-jre8-mpdemo:latest
name: rhel7-jre8-mpdemo
ports:
- containerPort: 8080
protocol: TCP
replicas: 1
triggers:
- type: ConfigChange
- imageChangeParams:
automatic: true
containerNames:
- rhel7-jre8-mpdemo
from:
kind: ImageStreamTag
name: rhel7-jre8-mpdemo:latest
type: ImageChange

サービス

これでデプロイメントができたので、内部のロードバランシングやポッドのIPアドレスなどを確保するサービスも定義したいと思います。

サービスは、新しく作成したアプリを最終的に外部のトラフィックに公開したい場合に重要です。

- apiVersion: v1
kind: Service
metadata:
name: rhel7-jre8-mpdemo
spec:
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
selector:
deploymentconfig: rhel7-jre8-mpdemo

ルート

そして、デプロイメントの最後の部品は、ルートです。ルートを使ってアプリを外部に公開する時が来ました。このルートがどの内部サービスを指すのか、どのポートをターゲットにするのかを定義できます。OpenShift はルートにフレンドリーな URL を与えます。この URL を指定することで、新しく作成した Java 8 ランタイムベースのデプロイメント上で MicroProfile アプリが実行されるのを確認できます。

- apiVersion: v1
kind: Route
metadata:
name: rhel7-jre8-mpdemo
spec:
port:
targetPort: 8080-tcp
to:
kind: Service
name: rhel7-jre8-mpdemo
weight: 100

上記の完全なテンプレートはGitHubのここにあります。

また、このようにOpenShiftでプロジェクトを作成してみましょう。

$ oc new-project jredemos

そして、テンプレートを処理して、OpenShift上でJava 8ランタイムを使ったデモを取得します。そのためには、以下のコマンドを実行します。

$ oc process -f deployment.yaml  | oc create -f -

これでデプロイメント全体が作成され、以下のように表示されるはずです。

https://developers.redhat.com/blog/wp-content/uploads/2019/02/screenshot1-300x33.png

ここで、次のコマンドを実行します。

$ oc get routes

これにより、以下のようなルートが表示されます。

https://developers.redhat.com/blog/wp-content/uploads/2019/02/screenshot2-300x9.png

このルートをブラウザにコピーすると、RHEL 7上でJava 8ランタイムが動作するWebアプリがデプロイされていることが確認できます。(以下のアドレスは、クラスタのテスト専用であり、クラスタごとに異なります)

http://rhel7-jre8-mpdemo-jredemos.apps.cluster-1fda.1fda.openshiftworkshop.com/

まとめ

DockerまたはBuildahを使って、Java 8ランタイムのコンテナイメージを構築・作成することに成功しました。以下の点に注意してください。

  • この画像は、どのようにして実現するかを示すためのものであることに注意してください。JolokioやHawkularのような、デプロイに必要なものは含まれていません。
  • さらに、コンテナ内でJavaアプリを実行するために必要なパラメータは考慮されていません。これについては、Rafael Benevides氏の記事で非常によく説明されています。
  • さらに、独自のコンテナイメージをデプロイする際には、Red Hat の OpenJDK ビルドを実行している場合、サポートおよびライフサイクルポリシー こちら を確認することを常に忘れないでください。

その後、MicroProfile Starter betaから基本的なMicroProfileのデモアプリを使ってOpenShiftにデプロイしました。

より包括的なデモアプリの作成を検討されている方は、以下の資料をご参照ください。

本記事の全資料はこちらからご覧いただけます。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。