昨日MicronautとDockerを触りながら「そういえばJibってのがあったけど触ってなかったなぁ」と思ったので触ってみた。感想は「気の利くやつだな」。
## Jib?
Googleの提供してるコンテナ化ツール。
去年の夏頃発表されたんだっけな。
通常、Javaのアプリをコンテナ化するときって、例えばSpringBootとかMicronautだと
という手順になるのだけど、Jibを使うとDockerfileを書かなくても空気を読んでGradleやMavenでコンテナのビルドやpushまでコマンドひとつでやってくれる。*1
それと、Dockerデーモンがなくてもビルドできるみたい。ローカルだとDockerは入れておくだろうけど、CIサーバーとかだとDockerなくても大丈夫ってのは良さそう。
## MicronautのアプリをGCRにpushしてみる
この辺を読みながらやってみた。
https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin
### build.gradle
まずは、Micronautのプロジェクトを作るところから始めてみた*2
❯ mn create-app hello-jib --features spock
| Generating Java project...
| Application created at /home/bufferings/workspace/micronaut/hello-jib
で、build.gradleにjibの設定を入れる。プラグインの部分と、生成するイメージの名前。
plugins { id "io.spring.dependency-management" version "1.0.6.RELEASE" id "com.github.johnrengelman.shadow" version "4.0.2" id "application" id "groovy" id "java" id "net.ltgt.apt-eclipse" version "0.21" id "net.ltgt.apt-idea" version "0.21" // これ id 'com.google.cloud.tools.jib' version '1.0.2' } // これ jib.to.image = 'asia.gcr.io/bufferings/my-app'
Google Container Registryにpushしてみようかなと思ったので、イメージ名はそうしといた。
### GCR用のクレデンシャルを用意
Make sure you have the docker-credential-gcr command line tool. Jib automatically uses docker-credential-gcr for obtaining credentials. See Authentication Methods for other ways of authenticating.
って書いてあるので、設定しといた。
❯ docker-credential-gcr configure-docker
/home/bufferings/.docker/config.json configured to use this credential helper for GCR registries
### 実行!
のためのGradleタスクはこの2つ
./gradlew jib
→ ビルドしてレジストリーにpushする./graldew jibDockerBuild
→ ローカルのDockerデーモンに対してイメージのビルドをする
とりあえず、前者の ./gradlew jib
を実行してみたら、エラーになった。
❯ ./gradlew jib > Task :compileJava warning: Supported source version 'RELEASE_11' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '12' warning: Supported source version 'RELEASE_11' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '12' warning: Supported source version 'RELEASE_11' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '12' 3 warnings > Task :jib FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':jib'. > Your project is using Java 12 but the base image is for Java 11, perhaps you should configure a Java 12-compatible base image using the 'jib.from.image' parameter, or set targetCompatibility = 11 o r below in your build configuration * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 4s 3 actionable tasks: 3 executed
Java 12使ってたけど、Base Imageは11じゃよ。って怒られた。JibはデフォルトでDistroless/javaを使うらしいんだけど、それがJava 11ってことか。そっか。
❯ sdk use java 11.0.2-open
Using java version 11.0.2-open in this shell.
これでいけるかな。
❯ ./gradlew jib Starting a Gradle Daemon, 1 incompatible and 2 stopped Daemons could not be reused, use --status for details Containerizing application to asia.gcr.io/bufferings/my-app... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, hello.jib.Application] Built and pushed image as asia.gcr.io/bufferings/my-app Executing tasks: [==============================] 100.0% complete BUILD SUCCESSFUL in 2m 4s 3 actionable tasks: 2 executed, 1 up-to-date
レジストリー見てみたら、ちゃんとpushされてるー。(∩´∀`)∩ワーイ
### pullしてみるか
じゃ、pullして実行できるの確認しとこかな?と思ったけど、そのまえに、そもそも、実はビルド時にローカルにも登録されてたりしないのかな?と思って見てみた。
❯ docker images | grep gcr asia.gcr.io/bufferings/quickstart-image tag1 e1ddd7948a1c 8 months ago 1.16MB gcr.io/distroless/java latest d53055d7a4da 49 years ago 118MB
ないね。じゃ、やってみよ。
❯ docker run --rm -p 8080:8080 asia.gcr.io/bufferings/my-app Unable to find image 'asia.gcr.io/bufferings/my-app:latest' locally latest: Pulling from bufferings/my-app f6045256ec3f: Pull complete 5f5edd681dcb: Pull complete 3e010093287c: Pull complete e6476c6c5a02: Pull complete 4988a9948f57: Pull complete ffc771f05eaa: Pull complete 45a6b543af72: Pull complete Digest: sha256:eeb9e44406fb12dc4ed318c2ca56d36db065a8dbbae32d435526a50e65f33d39 Status: Downloaded newer image for asia.gcr.io/bufferings/my-app:latest 01:30:48.626 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2115ms. Server Running: http://a1151605f84c:8080 ^C01:32:10.753 [Thread-2] INFO io.micronaut.runtime.Micronaut - Embedded Application shutting down
OK。
## 中身が気になる
中身が気になるなー。どうなってるんだろうなー?
### Entrypoint
まずはEntrypointを見てみた。さっきビルドしたときにも出てきたな。
❯ docker inspect asia.gcr.io/bufferings/my-app | jq '.[] | .Config.Entrypoint' [ "java", "-cp", "/app/resources:/app/classes:/app/libs/*", "hello.jib.Application" ]
ふーん。
### 中に入ってみる
Distrolessにはshも入ってないから、デバッグ用に中に入って色々見てみたりしたいならdebugタグを使ってねってFAQに書いてある。
https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md#where-is-bash
If you would like to include a shell for debugging, set the base image to gcr.io/distroless/java:debug instead. The shell will be located at /busybox/sh. Note that :debug images are not recommended for production use.
おすおす。こんな感じに書き換えてみた。
id 'com.google.cloud.tools.jib' version '1.0.2' } jib { from { // これを足した image = 'gcr.io/distroless/java:debug' } to { image = 'asia.gcr.io/bufferings/my-app' } }
で、こんどはpushしなくてもいいからローカル用に jibDockerBuild
でビルド。したら、エラー。
❯ ./gradlew jibDockerBuild > Task :jibDockerBuild FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':jibDockerBuild'. > Your project is using Java 11 but the base image is for Java 8, perhaps you should configure a Java 11-compatible base image using the 'jib.from.image' parameter, or set targetCompatibility = 8 or below in your build configuration * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 1s 3 actionable tasks: 1 executed, 2 up-to-date
あら。debugタグはJava 8なのか。
❯ sdk use java 8.0.202.hs-adpt
Using java version 8.0.202.hs-adpt in this shell.
8に変えて、ビルド。
❯ ./gradlew jibDockerBuild Starting a Gradle Daemon, 2 incompatible Daemons could not be reused, use --status for details Containerizing application to Docker daemon as asia.gcr.io/bufferings/my-app... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, hello.jib.Application] Built image to Docker daemon as asia.gcr.io/bufferings/my-app Executing tasks: [==============================] 100.0% complete BUILD SUCCESSFUL in 35s 3 actionable tasks: 2 executed, 1 up-to-date
おっけー。
じゃ、中に入ってみてみるかー。
❯ docker run --rm -ti --entrypoint /busybox/sh asia.gcr.io/bufferings/my-app / # find /app /app /app/libs /app/libs/netty-codec-4.1.30.Final.jar /app/libs/netty-transport-4.1.30.Final.jar /app/libs/micronaut-http-client-1.1.0.jar /app/libs/jackson-core-2.9.8.jar /app/libs/micronaut-core-1.1.0.jar /app/libs/netty-handler-4.1.30.Final.jar /app/libs/netty-buffer-4.1.30.Final.jar /app/libs/micronaut-http-1.1.0.jar /app/libs/micronaut-aop-1.1.0.jar /app/libs/jackson-databind-2.9.8.jar /app/libs/netty-codec-socks-4.1.30.Final.jar /app/libs/netty-handler-proxy-4.1.30.Final.jar /app/libs/validation-api-2.0.1.Final.jar /app/libs/javax.annotation-api-1.3.2.jar /app/libs/jackson-annotations-2.9.8.jar /app/libs/netty-resolver-4.1.30.Final.jar /app/libs/jsr305-3.0.2.jar /app/libs/slf4j-api-1.7.25.jar /app/libs/micronaut-validation-1.1.0.jar /app/libs/netty-common-4.1.30.Final.jar /app/libs/micronaut-http-netty-1.1.0.jar /app/libs/javax.inject-1.jar /app/libs/micronaut-http-server-netty-1.1.0.jar /app/libs/micronaut-runtime-1.1.0.jar /app/libs/logback-core-1.2.3.jar /app/libs/jackson-datatype-jsr310-2.9.8.jar /app/libs/reactive-streams-1.0.2.jar /app/libs/micronaut-buffer-netty-1.1.0.jar /app/libs/micronaut-websocket-1.1.0.jar /app/libs/logback-classic-1.2.3.jar /app/libs/jackson-datatype-jdk8-2.9.8.jar /app/libs/rxjava-2.2.6.jar /app/libs/snakeyaml-1.23.jar /app/libs/netty-codec-http-4.1.30.Final.jar /app/libs/micronaut-inject-1.1.0.jar /app/libs/micronaut-http-server-1.1.0.jar /app/libs/micronaut-router-1.1.0.jar /app/classes /app/classes/hello /app/classes/hello/jib /app/classes/hello/jib/Application.class /app/resources /app/resources/application.yml /app/resources/logback.xml
ふーん。libsに依存ライブラリーが入って、classesにクラスファイルが、resourcesにはリソースファイルが入るのか。なるほどなー。気の利くやつだな。
## その他
細かく色々設定できるみたい。
https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin
環境変数とかは普通に外から渡せば良さそう。
おしまい。これくらいメモ残しておけば、また使いたくなったときに思い出せるかな。