これは、なにをしたくて書いたもの?
Spring Boot 2.3から、Cloud Native Buildpacksを使ったDockerイメージの作成ができるというので、ちょっと試しておこうかなと。
Support for building Docker images using Cloud Native Buildpacks
Spring Boot 2.3.0.M1 is now available
Mavenのゴール、Gradleのタスクとして実行できるようです。
Support for building Docker images using Cloud Native Buildpacks and has been added to the Maven and Gradle plugins via the spring-boot:build-image goal and the bootBuildImage task.
Spring Boot 2.3.0 available now
Cloud Native Buildpacks
Cloud Native Buildpacksは、HerokuやCloud Foundryが作成した、コンテナイメージを作る仕組みです。
Cloud Native Buildpacks · Cloud Native Buildpacks
が、今回はとりあえず「そういうものだ」ということにしてあまり詳細には踏み込まず、まずはSpring BootでDockerイメージを
作るところをやってみたいと思います。
Spring BootとCloud Native Buildpacks
Spring Bootのドキュメントを見ると、コンテナイメージ作成についての記述があります。
Building Container Images / Buildpacks
Cloud Native Buildpacksのところを見ると、Maven PluginやGradle Pluginのドキュメントを見てね、と言われますが。
今回は、Maven Pluginの方で見ていきます。spring-boot:build-image
ゴールで、コンテナイメージが作れるようです。
Spring Boot Maven Plugin Documentation / Packaging OCI Images
では、ここまでの情報から簡単に試していってみましょう。
環境
今回の環境は、こちら。
$ java --version openjdk 11.0.8 2020-07-14 OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04) OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode, sharing) $ mvn --version Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 11.0.8, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "4.15.0-112-generic", arch: "amd64", family: "unix" $ docker version Client: Docker Engine - Community Version: 19.03.13 API version: 1.40 Go version: go1.13.15 Git commit: 4484c46d9d Built: Wed Sep 16 17:02:52 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.13 API version: 1.40 (minimum version 1.12) Go version: go1.13.15 Git commit: 4484c46d9d Built: Wed Sep 16 17:01:20 2020 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.3.7 GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683
プロジェクトの作成
Spring Bootプロジェクトを作成します。
$ curl -s https://start.spring.io/starter.tgz -d dependencies=web \ -d groupId=org.littlewings -d artifactId=buildpacks-example \ -d packageName=org.littlewings.spring.buildpacs \ -d baseDir=buildpacks-example | tar -xzvf - $ cd buildpacks-example
Spring Bootのバージョンは、2.3.4.RELEASEです。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
依存関係。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
Spring Boot Maven Plugin。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
ここまでは、自動生成された内容の抜粋です。
このままでも良いのですが、Controllerをひとつ追加しておきましょう。
src/main/java/org/littlewings/spring/buildpacs/HelloController.java
package org.littlewings.spring.buildpacs; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("hello") @RestController public class HelloController { @GetMapping public String message() { return "Hello World!!"; } }
この状態で、1度ビルドして、起動。
$ mvn package -DskipTests=true $ java -jar target/buildpacks-example-0.0.1-SNAPSHOT.jar
確認。
$ curl localhost:8080/hello Hello World!!
OKなので、1度mvn clean
しておきます。
$ mvn clean
Dockerイメージを作成する
では、Dockerイメージを作ってみましょう。
mvn spring-boot:build-image
を実行してみます。
$ mvn spring-boot:build-image -DskipTests=true
JARを作成した後、必要なイメージのダウンロードが行われ(※すでにダウンロードされている場合は行われません)、
Dockerイメージがビルドされます。
[INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ buildpacks-example --- [INFO] Building jar: /path/to/buildpacks-example/target/buildpacks-example-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- spring-boot-maven-plugin:2.3.4.RELEASE:repackage (repackage) @ buildpacks-example --- [INFO] Replacing main artifact with repackaged archive [INFO] [INFO] <<< spring-boot-maven-plugin:2.3.4.RELEASE:build-image (default-cli) < package @ buildpacks-example <<< [INFO] [INFO] [INFO] --- spring-boot-maven-plugin:2.3.4.RELEASE:build-image (default-cli) @ buildpacks-example --- [INFO] Building image 'docker.io/library/buildpacks-example:0.0.1-SNAPSHOT' [INFO] [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 0% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 6% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 9% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 12% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 15% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 17% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 19% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 22% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 25% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 28% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 31% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 35% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 40% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 47% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 54% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 62% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 70% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 74% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 80% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 84% [INFO] > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 100% [INFO] > Pulled builder image 'gcr.io/paketo-buildpacks/builder@sha256:aa375d2c194d7f16d7a7bb704c5d1cebf77a516326ec6e9f4b5230893457f89e' [INFO] > Pulling run image 'docker.io/paketobuildpacks/run:base-cnb' 0% [INFO] > Pulling run image 'docker.io/paketobuildpacks/run:base-cnb' 17% [INFO] > Pulling run image 'docker.io/paketobuildpacks/run:base-cnb' 100% [INFO] > Pulled run image 'paketobuildpacks/run@sha256:3175edc5a0570b41b2109c53786890cca575570d71bbe734bb001f0b5aad4508' [INFO] > Executing lifecycle version v0.9.1 [INFO] > Using build cache volume 'pack-cache-bba3705ad090.build' [INFO] [INFO] > Running creator [INFO] [creator] ===> DETECTING [INFO] [creator] 5 of 17 buildpacks participating [INFO] [creator] paketo-buildpacks/bellsoft-liberica 4.0.0 [INFO] [creator] paketo-buildpacks/executable-jar 3.1.1 [INFO] [creator] paketo-buildpacks/apache-tomcat 2.3.0 [INFO] [creator] paketo-buildpacks/dist-zip 2.2.0 [INFO] [creator] paketo-buildpacks/spring-boot 3.2.1 [INFO] [creator] ===> ANALYZING [INFO] [creator] Previous image with name "docker.io/library/buildpacks-example:0.0.1-SNAPSHOT" not found [INFO] [creator] ===> RESTORING [INFO] [creator] ===> BUILDING [INFO] [creator] [INFO] [creator] Paketo BellSoft Liberica Buildpack 4.0.0 [INFO] [creator] https://github.com/paketo-buildpacks/bellsoft-liberica [INFO] [creator] Build Configuration: [INFO] [creator] $BP_JVM_VERSION 11.* the Java version [INFO] [creator] Launch Configuration: [INFO] [creator] $BPL_JVM_HEAD_ROOM 0 the headroom in memory calculation [INFO] [creator] $BPL_JVM_LOADED_CLASS_COUNT 35% of classes the number of loaded classes in memory calculation [INFO] [creator] $BPL_JVM_THREAD_COUNT 250 the number of threads in memory calculation [INFO] [creator] $JAVA_TOOL_OPTIONS the JVM launch flags [INFO] [creator] BellSoft Liberica JRE 11.0.8: Contributing to layer [INFO] [creator] Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.8+10/bellsoft-jre11.0.8+10-linux-amd64.tar.gz [INFO] [creator] Verifying checksum [INFO] [creator] Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jre [INFO] [creator] Adding 127 container CA certificates to JVM truststore [INFO] [creator] Writing env.launch/BPI_APPLICATION_PATH.default [INFO] [creator] Writing env.launch/BPI_JVM_CACERTS.default [INFO] [creator] Writing env.launch/BPI_JVM_CLASS_COUNT.default [INFO] [creator] Writing env.launch/BPI_JVM_SECURITY_PROVIDERS.default [INFO] [creator] Writing env.launch/JAVA_HOME.default [INFO] [creator] Writing env.launch/MALLOC_ARENA_MAX.default [INFO] [creator] Launch Helper: Contributing to layer [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/active-processor-count [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/java-opts [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/link-local-dns [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/openssl-certificate-loader [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/security-providers-configurer [INFO] [creator] Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/security-providers-classpath-9 [INFO] [creator] Writing profile.d/helper [INFO] [creator] JVMKill Agent 1.16.0: Contributing to layer [INFO] [creator] Downloading from https://github.com/cloudfoundry/jvmkill/releases/download/v1.16.0.RELEASE/jvmkill-1.16.0-RELEASE.so [INFO] [creator] Verifying checksum [INFO] [creator] Copying to /layers/paketo-buildpacks_bellsoft-liberica/jvmkill [INFO] [creator] Writing env.launch/JAVA_TOOL_OPTIONS.append [INFO] [creator] Writing env.launch/JAVA_TOOL_OPTIONS.delim [INFO] [creator] Java Security Properties: Contributing to layer [INFO] [creator] Writing env.launch/JAVA_SECURITY_PROPERTIES.default [INFO] [creator] Writing env.launch/JAVA_TOOL_OPTIONS.append [INFO] [creator] Writing env.launch/JAVA_TOOL_OPTIONS.delim [INFO] [creator] [INFO] [creator] Paketo Executable JAR Buildpack 3.1.1 [INFO] [creator] https://github.com/paketo-buildpacks/executable-jar [INFO] [creator] Writing env.launch/CLASSPATH.delim [INFO] [creator] Writing env.launch/CLASSPATH.prepend [INFO] [creator] Process types: [INFO] [creator] executable-jar: java org.springframework.boot.loader.JarLauncher [INFO] [creator] task: java org.springframework.boot.loader.JarLauncher [INFO] [creator] web: java org.springframework.boot.loader.JarLauncher [INFO] [creator] [INFO] [creator] Paketo Spring Boot Buildpack 3.2.1 [INFO] [creator] https://github.com/paketo-buildpacks/spring-boot [INFO] [creator] Launch Helper: Contributing to layer [INFO] [creator] Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings [INFO] [creator] Writing profile.d/helper [INFO] [creator] Web Application Type: Contributing to layer [INFO] [creator] Servlet web application detected [INFO] [creator] Writing env.launch/BPL_JVM_THREAD_COUNT.default [INFO] [creator] Spring Cloud Bindings 1.6.0: Contributing to layer [INFO] [creator] Downloading from https://repo.spring.io/release/org/springframework/cloud/spring-cloud-bindings/1.6.0/spring-cloud-bindings-1.6.0.jar [INFO] [creator] Verifying checksum [INFO] [creator] Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings [INFO] [creator] Image labels: [INFO] [creator] org.opencontainers.image.title [INFO] [creator] org.opencontainers.image.version [INFO] [creator] org.springframework.boot.spring-configuration-metadata.json [INFO] [creator] org.springframework.boot.version [INFO] [creator] ===> EXPORTING [INFO] [creator] Adding layer 'paketo-buildpacks/bellsoft-liberica:helper' [INFO] [creator] Adding layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties' [INFO] [creator] Adding layer 'paketo-buildpacks/bellsoft-liberica:jre' [INFO] [creator] Adding layer 'paketo-buildpacks/bellsoft-liberica:jvmkill' [INFO] [creator] Adding layer 'paketo-buildpacks/executable-jar:class-path' [INFO] [creator] Adding layer 'paketo-buildpacks/spring-boot:helper' [INFO] [creator] Adding layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings' [INFO] [creator] Adding layer 'paketo-buildpacks/spring-boot:web-application-type' [INFO] [creator] Adding 1/1 app layer(s) [INFO] [creator] Adding layer 'launcher' [INFO] [creator] Adding layer 'config' [INFO] [creator] Adding label 'io.buildpacks.lifecycle.metadata' [INFO] [creator] Adding label 'io.buildpacks.build.metadata' [INFO] [creator] Adding label 'io.buildpacks.project.metadata' [INFO] [creator] Adding label 'org.opencontainers.image.title' [INFO] [creator] Adding label 'org.opencontainers.image.version' [INFO] [creator] Adding label 'org.springframework.boot.spring-configuration-metadata.json' [INFO] [creator] Adding label 'org.springframework.boot.version' [INFO] [creator] *** Images (7bf9a3ad6c35): [INFO] [creator] docker.io/library/buildpacks-example:0.0.1-SNAPSHOT [INFO] [INFO] Successfully built image 'docker.io/library/buildpacks-example:0.0.1-SNAPSHOT' [INFO]
今回は、2分かからない程度でした。イメージのダウンロードがありましたからね。
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:48 min [INFO] Finished at: 2020-10-08T23:19:24+09:00 [INFO] ------------------------------------------------------------------------
ちなみに、1度mvn clean
してから、もう1度Dockerイメージを作ってみると、このくらいの時間でした。
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 10.547 s [INFO] Finished at: 2020-10-08T23:51:19+09:00 [INFO] ------------------------------------------------------------------------
できあがったDockerイメージと、ビルド時にダウンロードしてきたイメージ。
$ docker image ls | grep -E 'buildpacks|paketo' paketobuildpacks/run base-cnb b4873a43e158 11 days ago 83.3MB gcr.io/paketo-buildpacks/builder base-platform-api-0.3 ef7046f41e9b 40 years ago 666MB buildpacks-example 0.0.1-SNAPSHOT 7bf9a3ad6c35 40 years ago 253MB
なんと、できあがったイメージは40年前になっています。
とりあえず、起動してみましょう。
shell $ docker container run -it --rm -p 8080:8080 --name example buildpacks-example:0.0.1-SNAPSHOT
起動時のログ。
Setting Active Processor Count to 8 WARNING: Container memory limit unset. Configuring JVM for 1G container. Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 1G, Thread Count: 250, Loaded Class Count: 11967, Headroom: 0%) Adding 127 container CA certificates to JVM truststore Spring Cloud Bindings Enabled Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=8 -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.4.RELEASE) 2020-10-08 14:21:50.960 INFO 1 --- [ main] o.l.spring.buildpacs.DemoApplication : Starting DemoApplication v0.0.1-SNAPSHOT on e6936ba8608a with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace) 2020-10-08 14:21:50.963 INFO 1 --- [ main] o.l.spring.buildpacs.DemoApplication : No active profile set, falling back to default profiles: default 2020-10-08 14:21:52.052 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2020-10-08 14:21:52.071 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2020-10-08 14:21:52.072 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.38] 2020-10-08 14:21:52.150 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2020-10-08 14:21:52.150 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1113 ms 2020-10-08 14:21:52.400 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-10-08 14:21:52.614 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-10-08 14:21:52.632 INFO 1 --- [ main] o.l.spring.buildpacs.DemoApplication : Started DemoApplication in 2.146 seconds (JVM running for 2.611) 2020-10-08 14:22:07.506 INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2020-10-08 14:22:07.506 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2020-10-08 14:22:07.512 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 6 ms
コンテナ実行時に、リソース制限を入れていないので、怒られていますね…。
WARNING: Container memory limit unset. Configuring JVM for 1G container.
JavaVMに関する設定が行われているようです。
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 1G, Thread Count: 250, Loaded Class Count: 11967, Headroom: 0%) Adding 127 container CA certificates to JVM truststore Spring Cloud Bindings Enabled Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=8 -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
アプリケーションの場所は、こちらのようですね。
2020-10-08 14:21:50.960 INFO 1 --- [ main] o.l.spring.buildpacs.DemoApplication : Starting DemoApplication v0.0.1-SNAPSHOT on e6936ba8608a with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
ホスト側から、curl
で確認してみます。
$ curl localhost:8080/hello Hello World!!
動いているようです。OKですね。
少し、コンテナの中身を
コンテナの中を少し見てみましょう。
$ docker container exec -it example bash cnb@e6936ba8608a:/$
Ubuntu Linux 18.04 LTSのようです。
$ uname -a Linux e6936ba8608a 4.15.0-112-generic #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/os-release NAME="Ubuntu" VERSION="18.04.5 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.5 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic
起動しているプロセス。
$ ps -ef | grep java | grep -v grep cnb 1 0 9 14:21 pts/0 00:00:10 java org.springframework.boot.loader.JarLauncher
/workspace
配下に、作成したアプリケーションや、Spring Bootのライブラリ等が置かれているようです。
$ find /workspace -type f /workspace/META-INF/maven/org.littlewings/buildpacks-example/pom.xml /workspace/META-INF/maven/org.littlewings/buildpacks-example/pom.properties /workspace/META-INF/MANIFEST.MF /workspace/org/springframework/boot/loader/MainMethodRunner.class /workspace/org/springframework/boot/loader/util/SystemPropertyUtils.class /workspace/org/springframework/boot/loader/JarLauncher.class /workspace/org/springframework/boot/loader/ClassPathIndexFile.class /workspace/org/springframework/boot/loader/PropertiesLauncher.class /workspace/org/springframework/boot/loader/archive/JarFileArchive.class /workspace/org/springframework/boot/loader/archive/JarFileArchive$AbstractIterator.class /workspace/org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class /workspace/org/springframework/boot/loader/archive/ExplodedArchive.class /workspace/org/springframework/boot/loader/archive/ExplodedArchive$AbstractIterator.class /workspace/org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class /workspace/org/springframework/boot/loader/archive/Archive$EntryFilter.class /workspace/org/springframework/boot/loader/archive/ExplodedArchive$ArchiveIterator.class /workspace/org/springframework/boot/loader/archive/ExplodedArchive$EntryIterator.class /workspace/org/springframework/boot/loader/archive/JarFileArchive$NestedArchiveIterator.class /workspace/org/springframework/boot/loader/archive/Archive.class /workspace/org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class /workspace/org/springframework/boot/loader/archive/Archive$Entry.class /workspace/org/springframework/boot/loader/archive/ExplodedArchive$SimpleJarFileArchive.class /workspace/org/springframework/boot/loader/jarmode/JarModeLauncher.class /workspace/org/springframework/boot/loader/jarmode/TestJarMode.class /workspace/org/springframework/boot/loader/jarmode/JarMode.class /workspace/org/springframework/boot/loader/Launcher.class /workspace/org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class /workspace/org/springframework/boot/loader/PropertiesLauncher$1.class /workspace/org/springframework/boot/loader/jar/JarFile.class /workspace/org/springframework/boot/loader/jar/AbstractJarFile$JarFileType.class /workspace/org/springframework/boot/loader/jar/JarFileEntries.class /workspace/org/springframework/boot/loader/jar/JarURLConnection$1.class /workspace/org/springframework/boot/loader/jar/JarURLConnection.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryEndRecord$Zip64End.class /workspace/org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class /workspace/org/springframework/boot/loader/jar/ZipInflaterInputStream.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryEndRecord$Zip64Locator.class /workspace/org/springframework/boot/loader/jar/JarFileEntries$1.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryParser.class /workspace/org/springframework/boot/loader/jar/AbstractJarFile.class /workspace/org/springframework/boot/loader/jar/JarEntry.class /workspace/org/springframework/boot/loader/jar/Bytes.class /workspace/org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class /workspace/org/springframework/boot/loader/jar/AsciiBytes.class /workspace/org/springframework/boot/loader/jar/JarFile$JarEntryEnumeration.class /workspace/org/springframework/boot/loader/jar/JarFile$1.class /workspace/org/springframework/boot/loader/jar/StringSequence.class /workspace/org/springframework/boot/loader/jar/JarEntryCertification.class /workspace/org/springframework/boot/loader/jar/Handler.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class /workspace/org/springframework/boot/loader/jar/FileHeader.class /workspace/org/springframework/boot/loader/jar/JarEntryFilter.class /workspace/org/springframework/boot/loader/jar/JarFileWrapper.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryEndRecord$1.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryVisitor.class /workspace/org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class /workspace/org/springframework/boot/loader/LaunchedURLClassLoader$DefinePackageCallType.class /workspace/org/springframework/boot/loader/PropertiesLauncher$ClassPathArchives.class /workspace/org/springframework/boot/loader/WarLauncher.class /workspace/org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class /workspace/org/springframework/boot/loader/ExecutableArchiveLauncher.class /workspace/org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class /workspace/org/springframework/boot/loader/LaunchedURLClassLoader.class /workspace/org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class /workspace/org/springframework/boot/loader/data/RandomAccessDataFile.class /workspace/org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class /workspace/org/springframework/boot/loader/data/RandomAccessData.class /workspace/org/springframework/boot/loader/data/RandomAccessDataFile$1.class /workspace/BOOT-INF/lib/jul-to-slf4j-1.7.30.jar /workspace/BOOT-INF/lib/spring-boot-autoconfigure-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/spring-beans-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/logback-core-1.2.3.jar /workspace/BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar /workspace/BOOT-INF/lib/jackson-annotations-2.11.2.jar /workspace/BOOT-INF/lib/snakeyaml-1.26.jar /workspace/BOOT-INF/lib/spring-webmvc-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/spring-aop-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/tomcat-embed-websocket-9.0.38.jar /workspace/BOOT-INF/lib/jackson-core-2.11.2.jar /workspace/BOOT-INF/lib/spring-boot-starter-tomcat-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/spring-web-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/spring-core-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/spring-boot-starter-json-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/log4j-to-slf4j-2.13.3.jar /workspace/BOOT-INF/lib/spring-boot-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/jakarta.el-3.0.3.jar /workspace/BOOT-INF/lib/spring-boot-starter-logging-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/spring-context-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/jackson-datatype-jsr310-2.11.2.jar /workspace/BOOT-INF/lib/tomcat-embed-core-9.0.38.jar /workspace/BOOT-INF/lib/spring-boot-starter-web-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/spring-expression-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/jackson-module-parameter-names-2.11.2.jar /workspace/BOOT-INF/lib/spring-boot-starter-2.3.4.RELEASE.jar /workspace/BOOT-INF/lib/log4j-api-2.13.3.jar /workspace/BOOT-INF/lib/jackson-datatype-jdk8-2.11.2.jar /workspace/BOOT-INF/lib/slf4j-api-1.7.30.jar /workspace/BOOT-INF/lib/jackson-databind-2.11.2.jar /workspace/BOOT-INF/lib/spring-jcl-5.2.9.RELEASE.jar /workspace/BOOT-INF/lib/logback-classic-1.2.3.jar /workspace/BOOT-INF/classes/application.properties /workspace/BOOT-INF/classes/org/littlewings/spring/buildpacs/DemoApplication.class /workspace/BOOT-INF/classes/org/littlewings/spring/buildpacs/HelloController.class /workspace/BOOT-INF/classpath.idx
MANIFEST.MF
の中身。
/workspace/META-INF/MANIFEST.MF
Manifest-Version: 1.0 Created-By: Maven Jar Plugin 3.2.0 Build-Jdk-Spec: 11 Implementation-Title: demo Implementation-Version: 0.0.1-SNAPSHOT Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: org.littlewings.spring.buildpacs.DemoApplication Spring-Boot-Version: 2.3.4.RELEASE Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
起動クラスは、こちらにあります。
$ ll /workspace/org/springframework/boot/loader/JarLauncher.class -rw-r--r-- 1 cnb cnb 3966 Jan 1 1980 /workspace/org/springframework/boot/loader/JarLauncher.class
あと、このあたりのディレクトリも気になりますね。
$ ll /layers total 32 drwxr-xr-x 1 cnb cnb 4096 Jan 1 1980 ./ drwxr-xr-x 1 root root 4096 Oct 8 14:21 ../ drwxr-xr-x 2 cnb cnb 4096 Jan 1 1980 config/ drwxr-xr-x 1 cnb cnb 4096 Jan 1 1980 paketo-buildpacks_bellsoft-liberica/ drwxr-xr-x 3 cnb cnb 4096 Jan 1 1980 paketo-buildpacks_executable-jar/ drwxr-xr-x 1 cnb cnb 4096 Jan 1 1980 paketo-buildpacks_spring-boot/ $ ll /cnb total 12 drwxr-xr-x 3 root root 4096 Jan 1 1980 ./ drwxr-xr-x 1 root root 4096 Oct 8 14:21 ../ drwxr-xr-x 2 root root 4096 Jan 1 1980 lifecycle/
さて、Javaのバージョンは…コマンドが見つかりません。
$ java --version bash: java: command not found
なんか、このファイルを実行すると、起動するんですが。こちらがエントリーポイントみたいですね。
$ /cnb/lifecycle/launcher Setting Active Processor Count to 8 WARNING: Container memory limit unset. Configuring JVM for 1G container. Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 1G, Thread Count: 250, Loaded Class Count: 11967, Headroom: 0%) Adding 127 container CA certificates to JVM truststore Spring Cloud Bindings Enabled Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=8 -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.4.RELEASE) 2020-10-08 14:33:35.714 INFO 258 --- [ main] o.l.spring.buildpacs.DemoApplication : Starting DemoApplication v0.0.1-SNAPSHOT on e6936ba8608a with PID 258 (/workspace/BOOT-INF/classes started by cnb in /workspace)
すでにコンテナ自体を起動するのに同じアプリケーションを実行しているので、このまま放っておくとリッスンポートが衝突して停止します。
java
コマンドは、こちらにあるようです。
$ /layers/paketo-buildpacks_bellsoft-liberica/jre/bin/java --version openjdk 11.0.8 2020-07-14 LTS OpenJDK Runtime Environment (build 11.0.8+10-LTS) OpenJDK 64-Bit Server VM (build 11.0.8+10-LTS, mixed mode)
ここで、1度コンテナを終了。
JavaVMに起動オプションを渡すには、環境変数JAVA_OPTS
を使用するとよさそうです。
たとえば、-e JAVA_OPTS=-Dserver.port=9000
と指定してリッスンポートを9000
にしてみます。
※ホスト側へバインドするポートも変えています
$ docker container run -it --rm -p 9000:9000 -e JAVA_OPTS=-Dserver.port=9000 --name example buildpacks-example:0.0.1-SNAPSHOT Setting Active Processor Count to 8 Adding $JAVA_OPTS to $JAVA_TOOL_OPTIONS WARNING: Container memory limit unset. Configuring JVM for 1G container. Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 1G, Thread Count: 250, Loaded Class Count: 11967, Headroom: 0%) Adding 127 container CA certificates to JVM truststore Spring Cloud Bindings Enabled Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=8 -Dserver.port=9000 -XX:MaxDirectMemorySize=10M -Xmx455122K -XX:MaxMetaspaceSize=81453K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
JAVA_OPTS
の内容を、JAVA_TOOL_OPTIONS
に追加したよ、と出ていますね。
Adding $JAVA_OPTS to $JAVA_TOOL_OPTIONS
ログ上も変わっています。
2020-10-08 15:04:04.732 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9000 (http) with context path ''
確認。
$ curl localhost:9000/hello Hello World!!
OKです。
Spring Boot Maven Pluginをもう少し
Spring Boot Maven Pluginの設定回りは、こちら。
Dockerfile
のCOPY
やADD
みたいなものはなさそうですね…取り込む依存関係の調整ができるくらい、のように見えます。
ちなみに、イメージ内で使うJavaのバージョンは、プロジェクトのmaven.compiler.target
…つまりビルド指定に依存するようです。
The plugin detects the target Java compatibility of the project using the compiler’s plugin configuration or the maven.compiler.target property. By default, the plugin instructs the buildpacks to install the same Java version. You can override this behaviour by setting the BP_JVM_VERSION environment variable, see builder configuration.
BP_JVM_VERSION
環境変数でも指定できると書いてありますね。BP
???
話を変えて。
デフォルトのイメージ名はdocker.io/library/${project.artifactId}:${project.version}
のようなので、ちょっと変更してみましょう。
hello-spring-boot:0.0.1
としてみます。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <image> <name>hello-spring-boot:0.0.1</name> </image> </configuration> </plugin> </plugins> </build>
ビルド。
$ mvn spring-boot:build-image -DskipTests=true
Dockerイメージ名が変更できました。
[INFO] [creator] *** Images (eda4c877678d): [INFO] [creator] docker.io/library/hello-spring-boot:0.0.1 [INFO] [INFO] Successfully built image 'docker.io/library/hello-spring-boot:0.0.1'
次は、mvn package
でDockerイメージをビルドするようにしてみましょう。
こんな感じになります。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>build-image</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
mvn package
を実行すると、Dockerイメージができあがりますが、結果は割愛。
オマケ
今回はSpring Initializrでプロジェクトを作成しましたが、自分はparent
を使わずにSpring BootのBOMを扱うパターンもまあまあ
使うので、そちらのパターンでも書いておきます。
dependencyManagement
でBOMをimportして、
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.4.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Spring Boot Maven Pluginの設定はこんな感じにします。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.4.RELEASE</version> <executions> <execution> <goals> <goal>repackage</goal> <goal>build-image</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
これで、先ほどと同じように以下のコマンドでDockerイメージがビルドされます。
$ mvn package -DskipTests=true
Buildpackの方を少し
ところで、Dockerイメージのビルド時にこんなログが出ていました。
INFO] > Running creator [INFO] [creator] ===> DETECTING [INFO] [creator] 5 of 17 buildpacks participating [INFO] [creator] paketo-buildpacks/bellsoft-liberica 4.0.0 [INFO] [creator] paketo-buildpacks/executable-jar 3.1.1 [INFO] [creator] paketo-buildpacks/apache-tomcat 2.3.0 [INFO] [creator] paketo-buildpacks/dist-zip 2.2.0 [INFO] [creator] paketo-buildpacks/spring-boot 3.2.1 [INFO] [creator] ===> ANALYZING
これらの中から、spring-boot
が選択されたという感じでしょうか。
[INFO] [creator] Paketo BellSoft Liberica Buildpack 4.0.0 [INFO] [creator] https://github.com/paketo-buildpacks/bellsoft-liberica [INFO] [creator] Build Configuration: [INFO] [creator] $BP_JVM_VERSION 11.* the Java version [INFO] [creator] Launch Configuration: [INFO] [creator] $BPL_JVM_HEAD_ROOM 0 the headroom in memory calculation [INFO] [creator] $BPL_JVM_LOADED_CLASS_COUNT 35% of classes the number of loaded classes in memory calculation [INFO] [creator] $BPL_JVM_THREAD_COUNT 250 the number of threads in memory calculation [INFO] [creator] $JAVA_TOOL_OPTIONS the JVM launch flags [INFO] [creator] BellSoft Liberica JRE 11.0.8: Contributing to layer [INFO] [creator] Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.8+10/bellsoft-jre11.0.8+10-linux-amd64.tar.gz 〜省略〜 [INFO] [creator] Paketo Spring Boot Buildpack 3.2.1 [INFO] [creator] https://github.com/paketo-buildpacks/spring-boot [INFO] [creator] Launch Helper: Contributing to layer [INFO] [creator] Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings [INFO] [creator] Writing profile.d/helper [INFO] [creator] Web Application Type: Contributing to layer [INFO] [creator] Servlet web application detected [INFO] [creator] Writing env.launch/BPL_JVM_THREAD_COUNT.default [INFO] [creator] Spring Cloud Bindings 1.6.0: Contributing to layer [INFO] [creator] Downloading from https://repo.spring.io/release/org/springframework/cloud/spring-cloud-bindings/1.6.0/spring-cloud-bindings-1.6.0.jar [INFO] [creator] Verifying checksum [INFO] [creator] Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings [INFO] [creator] Image labels: [INFO] [creator] org.opencontainers.image.title [INFO] [creator] org.opencontainers.image.version [INFO] [creator] org.springframework.boot.spring-configuration-metadata.json [INFO] [creator] org.springframework.boot.version
こちらですね。Paketo Spring Boot Buildpackです
ベースは、Paketo BellSoft Liberica Buildpackな模様。
利用しているモジュールを見てみると
https://github.com/paketo-buildpacks/bellsoft-liberica/blob/v4.0.0/cmd/main/main.go
こういうのがあって、
少し中を見ると、JAVA_OPTS
をJAVA_TOOL_OPTIONS
に足している箇所がわかったりするので、実行時の情報も
このあたりになるんでしょうね。
https://github.com/paketo-buildpacks/libjvm/blob/v1.22.2/helper/java_opts.go#L30-L46
Spring Boot Maven Pluginの設定回りのソースコードは、こちら。
まだこのあたりの知識は全然ないので、そのうちCloud Native Buildpacksを単体で見てみようかなと思います。