こんにちは。 エキサイト株式会社の三浦です。
Javaアプリケーションをコンテナとして動かしたいとき、jibを使うのは大きな選択肢の1つです。
jibを使えば非常に簡単にJavaアプリケーションをコンテナ化することが出来ますが、一方でカスタマイズしたい場合に少し困ってしまう場合もあるのではないでしょうか。
今回はその一例として、jibでコンテナ化するJavaアプリケーションでSIGTERMを無視させる方法を紹介します。
jibとは
jibは、Javaアプリケーションを簡単にコンテナ化してくれるライブラリです。
Jib builds optimized Docker and OCI images for your Java applications without a Docker daemon - and without deep mastery of Docker best-practices. It is available as plugins for Maven and Gradle and as a Java library.
今回は、Gradleで使っていきます。
使い方としては簡単で、 build.gradle
に
plugins { id 'com.google.cloud.tools.jib' version '3.2.1' } ... jib { from { image = 'eclipse-temurin:17.0.2_8-jdk-alpine' } }
こんな形で設定をした後、
./gradlew jibDockerBuild -Djib.to.image=出力イメージ名
を実行すれば、ローカルのDockerデーモンにイメージが作成されます。
JVMの設定をしたい場合などは、以下のように少し設定を加えます。
jib { from { image = 'eclipse-temurin:17.0.2_8-jdk-alpine' } container { jvmFlags = ['-Duser.timezone=GMT+09', '-Xms1024M', '-Xmx1536M'] } }
単にイメージを作りたいだけならこれで良いのですが、今回の「SIGTERMを無視させる」ということをさせたい場合、少し複雑な設定をする必要があります。
jibでコンテナ化するJavaアプリケーションでSIGTERMを無視する方法
こちらで少し説明していますが、今回はSIGTERMを無視するために、dumb-initというライブラリを使用します。
このライブラリは受け取ったOSシグナルを別のシグナルに変換してアプリケーションに流すことができるのですが、設定次第で指定したOSシグナルをアプリケーションに流さず落とすことも出来ます。
今回はその設定を使うのですが、その場合、2つ課題があります。
- dumb-initを、DockerfileのRUNを使ってダウンロード・インストールする
- DockerfileのENTRYPOINTを書き換える
これらは、それぞれ別の方法で解決する必要があります。
jib使用時に、dumb-initをDockerfile内でダウンロード・インストールする
jibでは、Dockerfileにおける RUN
を設定できる項目は存在しません。
Running commands like apt-get slows down the container build process. We do not recommend or support running commands as part of the build.
そのため、jibの設定から RUN
を設定するのではなく、すでに RUN
を使って dumb-init
をインストールし終わったイメージをベースのイメージとして使用する必要があります。
まずは、以下のDockerfileを作成し、適当な名前でイメージを作成します。 (なお、Javaのバージョンは適宜変更してください)
FROM eclipse-temurin:17.0.2_8-jdk-alpine RUN apk update \ && apk add --upgrade dumb-init
今回は eclipse-temurin-custom:17.0.2_8-jdk-alpine
として作成したとします。
イメージを作成したら、以下のように設定すれば、そのイメージをjibがベースのイメージとして使用してくれます。
jib { from { image = 'docker://eclipse-temurin-custom:17.0.2_8-jdk-alpine' } container { jvmFlags = ['-Duser.timezone=GMT+09', '-Xms1024M', '-Xmx1536M'] } }
まずはこれで、 dumb-init
がインストールされたイメージをjibに使わせることが出来ました。
DockerfileのENTRYPOINTを書き換える
続いて、インストールをした dumb-init
を、 ENTRYPOINT
から使用します。
SIGTERMを無視するには、 ENTRYPOINT
で以下のように指定する必要があります。
ENTRYPOINT ["/usr/bin/dumb-init", "--rewrite", "15:0", "--", "以降は実行したいコマンド"]
jibでは、 ENTRYPOINT
を書き換える事自体は可能なのですが、少し複雑な設定が必要になります。
実はjibで ENTRYPOINT
を指定すると、先程の例に上げた jvmFlags
を含むいくつかの設定が使えなくなってしまうのです。
そこで、例えば
jib { from { image = 'docker://eclipse-temurin-custom:17.0.2_8-jdk-alpine' } container { jvmFlags = ['-Duser.timezone=GMT+09', '-Xms1024M', '-Xmx1536M'] } }
この設定をそのまま使用して dumb-init
を使用したい場合、jvmFlags
の設定自体も移植して以下のように指定する必要があります。
jib { from { image = 'docker://eclipse-temurin-custom:17.0.2_8-jdk-alpine' } container { creationTime = 'USE_CURRENT_TIMESTAMP' entrypoint = [ '/usr/bin/dumb-init', '--rewrite', '15:0', '--', 'java', '-Duser.timezone=GMT+09', '-Xms1024M', '-Xmx1536M', '-cp', '@/app/jib-classpath-file', '@/app/jib-main-class-file' ] } }
クラスパス・メインクラスも自分で設定する必要があるので注意しましょう。
なお、クラスパスは /app/jib-classpath-file
というファイルに、メインクラスは /app/jib-main-class-file
というファイルに自動的に書き出されるので、直接文字列で指定しなくてもそれらを使用すれば問題ないようです。
これでようやく、jibでコンテナ化したJavaアプリケーションがSIGTERMを無視してくれるようになりました。
最後に
jibは非常に便利なライブラリですが、その分複雑なことをしようとすると少し手間がかかる場合があります。
今回の記事が、そういったときに役に立てると幸いです。