--- title: Cloud Native Buildpacks Tutorial - 2.3. ┗ gcr.io/paketo-buildpacks/builder:base BuilderでJavaアプリ(Spring Boot)のOCIイメージを作成 tags: ["Cloud Native Buildpacks Tutorial", "Cloud Native Buildpacks", "Paketo", "Series"] categories: ["Dev", "Infrastructure", "CloudNativeBuildpacks", "Paketo"] date: 2020-04-28T07:52:18Z updated: 2020-05-11T09:33:43Z --- `gcr.io/paketo-buildpacks/builder:base`でJava(Spring Boot)のアプリケーションのOCIイメージを作成します。 BuilderとStackを予めpullしておいてください。 ``` docker pull gcr.io/paketo-buildpacks/builder:base docker pull gcr.io/paketo-buildpacks/run:base-cnb ``` 次のコマンドで"Hello World"アプリケーションを作成します。 ``` curl https://start.spring.io/starter.tgz \ -d artifactId=hello-spring-boot \ -d baseDir=hello-spring-boot \ -d dependencies=webflux \ -d packageName=hello \ -d applicationName=HelloSpringBootApplication | tar -xzvf - cd hello-spring-boot cat <<'EOF' > src/main/java/hello/HelloSpringBootApplication.java package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class HelloSpringBootApplication { @GetMapping("/") public String hello() { return "Hello World!"; } public static void main(String[] args) { SpringApplication.run(HelloSpringBootApplication.class, args); } } EOF ``` `pack build`コマンドでイメージを作成します。 Javaの場合はソースからビルドする方法とjar/warファイルからビルドする方法があります。 ### ソースからビルドする場合 ``` pack build making/pack-spring-boot --no-pull --builder gcr.io/paketo-buildpacks/builder:base ``` > BuilderとStackを事前にpullしていない場合は`--no-pull`を外せば、ビルド時にBuilderとStackもpullしますが、ビルドが遅くなります。 次のようなログが出力されます。 ``` ===> DETECTING [detector] 6 of 15 buildpacks participating [detector] paketo-buildpacks/bellsoft-liberica 2.5.3 [detector] paketo-buildpacks/maven 1.2.2 [detector] paketo-buildpacks/executable-jar 1.2.3 [detector] paketo-buildpacks/apache-tomcat 1.1.3 [detector] paketo-buildpacks/dist-zip 1.3.0 [detector] paketo-buildpacks/spring-boot 1.5.3 ===> ANALYZING [analyzer] Previous image with name "index.docker.io/making/pack-spring-boot:latest" not found ===> RESTORING ===> BUILDING [builder] [builder] Paketo BellSoft Liberica Buildpack 2.5.3 [builder] Set $BPL_JVM_HEAD_ROOM to configure the headroom in memory calculation. Default 0. [builder] Set $BPL_JVM_LOADED_CLASS_COUNT to configure the number of loaded classes in memory calculation. Default 35% of classes. [builder] Set $BPL_JVM_THREAD_COUNT to configure the number of threads in memory calculation. Default 250. [builder] Set $BP_JVM_VERSION to configure the Java version. Default 11.*. [builder] BellSoft Liberica JDK 11.0.7: Contributing to layer [builder] Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.7+10/bellsoft-jdk11.0.7+10-linux-amd64.tar.gz [builder] Verifying checksum [builder] Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jdk [builder] Populating with 133 container certificates [builder] Writing env.build/JAVA_HOME.override [builder] Writing env.build/JDK_HOME.override [builder] BellSoft Liberica JRE 11.0.7: Contributing to layer [builder] Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.7+10/bellsoft-jre11.0.7+10-linux-amd64.tar.gz [builder] Verifying checksum [builder] Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jre [builder] Writing env.launch/JAVA_HOME.override [builder] Writing env.launch/MALLOC_ARENA_MAX.override [builder] Writing profile.d/active-processor-count.sh [builder] Memory Calculator 4.0.0: Contributing to layer [builder] Downloading from https://github.com/cloudfoundry/java-buildpack-memory-calculator/releases/download/v4.0.0/memory-calculator-4.0.0.tgz [builder] Verifying checksum [builder] Expanding to /layers/paketo-buildpacks_bellsoft-liberica/memory-calculator [builder] Writing profile.d/memory-calculator.sh [builder] Class Counter: Contributing to layer [builder] Copying to /layers/paketo-buildpacks_bellsoft-liberica/class-counter [builder] JVMKill Agent 1.16.0: Contributing to layer [builder] Downloading from https://github.com/cloudfoundry/jvmkill/releases/download/v1.16.0.RELEASE/jvmkill-1.16.0-RELEASE.so [builder] Verifying checksum [builder] Copying to /layers/paketo-buildpacks_bellsoft-liberica/jvmkill [builder] Writing env.launch/JAVA_OPTS.append [builder] Link-Local DNS: Contributing to layer [builder] Copying to /layers/paketo-buildpacks_bellsoft-liberica/link-local-dns [builder] Writing profile.d/link-local-dns.sh [builder] Java Security Properties: Contributing to layer [builder] Writing env.launch/JAVA_OPTS.append [builder] Writing env.launch/JAVA_SECURITY_PROPERTIES.override [builder] Security Providers Configurer: Contributing to layer [builder] Copying to /layers/paketo-buildpacks_bellsoft-liberica/security-providers-configurer [builder] Writing profile.d/security-providers-classpath.sh [builder] Writing profile.d/security-providers-configurer.sh [builder] OpenSSL Security Provider 1.0.2: Contributing to layer [builder] Downloading from https://jitpack.io/com/github/paketo-buildpacks/openssl-security-provider/1.0.2/openssl-security-provider-1.0.2.jar [builder] Verifying checksum [builder] Copying to /layers/paketo-buildpacks_bellsoft-liberica/openssl-security-provider [builder] Writing env.launch/SECURITY_PROVIDERS.append [builder] Writing env.launch/SECURITY_PROVIDERS_CLASSPATH [builder] Writing profile.d/openssl-security-provider.sh [builder] [builder] Paketo Maven Buildpack 1.2.2 [builder] Set $BP_MAVEN_BUILD_ARGUMENTS to configure the arguments to pass to Maven. Default -Dmaven.test.skip=true package. [builder] Set $BP_MAVEN_BUILT_ARTIFACT to configure the built application artifact explicitly. Supersedes $BP_MAVEN_BUILT_MODULE. Default target/*.[jw]ar. [builder] Set $BP_MAVEN_BUILT_MODULE to configure the module to find application artifact in [builder] Set $BP_MAVEN_SETTINGS to configure the contents of a `settings.xml` file to be used at build time [builder] Creating cache directory /home/cnb/.m2 [builder] Compiled Application: Contributing to layer [builder] Executing mvnw -Dmaven.test.skip=true package [builder] [INFO] Scanning for projects... [builder] Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.7.RELEASE/spring-boot-starter-parent-2.2.7.RELEASE.pom Downloaded from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.7.RELEASE/spring-boot-starter-parent-2.2.7.RELEASE.pom (8.1 kB at 13 kB/s) [builder] Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-dependencies/2.2.7.RELEASE/spring-boot-dependencies-2.2.7.RELEASE.pom (途中略) [builder] [INFO] Replacing main artifact with repackaged archive [builder] [INFO] ------------------------------------------------------------------------ [builder] [INFO] BUILD SUCCESS [builder] [INFO] ------------------------------------------------------------------------ [builder] [INFO] Total time: 02:51 min [builder] [INFO] Finished at: 2020-05-11T02:37:14Z [builder] [INFO] ------------------------------------------------------------------------ [builder] Removing source code [builder] [builder] Paketo Executable JAR Buildpack 1.2.3 [builder] Writing env.launch/CLASSPATH [builder] Process types: [builder] executable-jar: java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher [builder] task: java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher [builder] web: java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher [builder] [builder] Paketo Spring Boot Buildpack 1.5.3 [builder] Image labels: [builder] org.opencontainers.image.title [builder] org.opencontainers.image.version [builder] org.springframework.boot.spring-configuration-metadata.json [builder] org.springframework.boot.version ===> EXPORTING [exporter] Adding layer 'launcher' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:class-counter' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:jre' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:jvmkill' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:link-local-dns' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:memory-calculator' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:openssl-security-provider' [exporter] Adding layer 'paketo-buildpacks/bellsoft-liberica:security-providers-configurer' [exporter] Adding layer 'paketo-buildpacks/executable-jar:class-path' [exporter] Adding 1/1 app layer(s) [exporter] Adding layer 'config' [exporter] *** Images (8db673ba510c): [exporter] index.docker.io/making/pack-spring-boot:latest [exporter] Adding cache layer 'paketo-buildpacks/bellsoft-liberica:jdk' [exporter] Adding cache layer 'paketo-buildpacks/maven:application' [exporter] Adding cache layer 'paketo-buildpacks/maven:cache' Successfully built image making/pack-spring-boot ``` > `pack build`時に`--publish`オプションをつけると、Docker Registryでのpushを行います。事前に`docker login`が必要です。 Mavenによるソースコードから始まるため、初回ビルド時には依存ライブラリのダウンロードが始まります。 依存ライブラリはキャッシュされ、二回目以降はキャッシュが使用されます。 > * JDKのバージョンはビルド時に[環境変数`$BP_JVM_VERSION`を設定](https://github.com/paketo-buildpacks/bellsoft-liberica#configuration)することで指定できます。デフォルトは`11.*`です。(例: `-e BP_JVM_VERSION=8.*`) `pack inspect-image`でイメージを解析します。 ``` $ pack inspect-image making/pack-spring-boot Inspecting image: making/pack-spring-boot REMOTE: (not present) LOCAL: Stack: io.buildpacks.stacks.bionic Base Image: Reference: 5b753a27144e7034add3089565bd3a18a4e5790efce0c9771d2ed4bb40d6fc60 Top Layer: sha256:2d0a8ddecbd1b537f555a120356f4dc9ff5855b2aa16b9d0edd7f9b5c3f9ade6 Run Images: gcr.io/paketo-buildpacks/run:base-cnb Buildpacks: ID VERSION paketo-buildpacks/bellsoft-liberica 2.5.3 paketo-buildpacks/maven 1.2.2 paketo-buildpacks/executable-jar 1.2.3 paketo-buildpacks/apache-tomcat 1.1.3 paketo-buildpacks/dist-zip 1.3.0 paketo-buildpacks/spring-boot 1.5.3 Processes: TYPE SHELL COMMAND ARGS web (default) bash java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher executable-jar bash java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher task bash java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher ``` Maven以外にもGradleによるビルドもサポートされています。 ### jarからビルドする場合 まずはソースコードをビルドしてjarファイルを作成します。 ``` mvn -Dmaven.test.skip=true clean package ``` `pack build`の`-p`オプションで作成したjarファイルのパスを指定します。 ``` pack build making/pack-spring-boot --no-pull -p target/hello-spring-boot-0.0.1-SNAPSHOT.jar --builder gcr.io/paketo-buildpacks/builder:base ``` 次のようなログが出力されます。 ``` ===> DETECTING [detector] 5 of 15 buildpacks participating [detector] paketo-buildpacks/bellsoft-liberica 2.5.3 [detector] paketo-buildpacks/executable-jar 1.2.3 [detector] paketo-buildpacks/apache-tomcat 1.1.3 [detector] paketo-buildpacks/dist-zip 1.3.0 [detector] paketo-buildpacks/spring-boot 1.5.3 ===> ANALYZING [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jre" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jvmkill" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:link-local-dns" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:memory-calculator" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:openssl-security-provider" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:security-providers-configurer" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:class-counter" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:java-security-properties" from app image [analyzer] Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jdk" from cache [analyzer] Restoring metadata for "paketo-buildpacks/executable-jar:class-path" from app image ===> RESTORING [restorer] Restoring data for "paketo-buildpacks/bellsoft-liberica:jdk" from cache ===> BUILDING [builder] [builder] Paketo BellSoft Liberica Buildpack 2.5.3 [builder] Set $BPL_JVM_HEAD_ROOM to configure the headroom in memory calculation. Default 0. [builder] Set $BPL_JVM_LOADED_CLASS_COUNT to configure the number of loaded classes in memory calculation. Default 35% of classes. [builder] Set $BPL_JVM_THREAD_COUNT to configure the number of threads in memory calculation. Default 250. [builder] Set $BP_JVM_VERSION to configure the Java version. Default 11.*. [builder] BellSoft Liberica JRE 11.0.7: Reusing cached layer [builder] Memory Calculator 4.0.0: Reusing cached layer [builder] Class Counter: Reusing cached layer [builder] JVMKill Agent 1.16.0: Reusing cached layer [builder] Link-Local DNS: Reusing cached layer [builder] Java Security Properties: Reusing cached layer [builder] Security Providers Configurer: Reusing cached layer [builder] OpenSSL Security Provider 1.0.2: Reusing cached layer [builder] [builder] Paketo Executable JAR Buildpack 1.2.3 [builder] Process types: [builder] executable-jar: java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher [builder] task: java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher [builder] web: java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher [builder] [builder] Paketo Spring Boot Buildpack 1.5.3 [builder] Image labels: [builder] org.opencontainers.image.title [builder] org.opencontainers.image.version [builder] org.springframework.boot.spring-configuration-metadata.json [builder] org.springframework.boot.version ===> EXPORTING [exporter] Reusing layer 'launcher' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:class-counter' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:jre' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:jvmkill' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:link-local-dns' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:memory-calculator' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:openssl-security-provider' [exporter] Reusing layer 'paketo-buildpacks/bellsoft-liberica:security-providers-configurer' [exporter] Reusing layer 'paketo-buildpacks/executable-jar:class-path' [exporter] Reusing 1/1 app layer(s) [exporter] Adding layer 'config' [exporter] *** Images (a012dcd34b64): [exporter] index.docker.io/making/pack-spring-boot:latest Successfully built image making/pack-spring-boot ``` 今回はイメージビルド時にMavenによるビルドは実行されません。 > * JDKのバージョンはビルド時に[環境変数`BP_JVM_VERSION`を設定](https://github.com/paketo-buildpacks/bellsoft-liberica#configuration)することで指定できます。デフォルトは`11.*`です。(例: `-e BP_JVM_VERSION=8.*`) `pack inspect-image`でイメージを解析します。 ``` $ pack inspect-image making/pack-spring-boot Inspecting image: making/pack-spring-boot REMOTE: (not present) LOCAL: Stack: io.buildpacks.stacks.bionic Base Image: Reference: 5b753a27144e7034add3089565bd3a18a4e5790efce0c9771d2ed4bb40d6fc60 Top Layer: sha256:2d0a8ddecbd1b537f555a120356f4dc9ff5855b2aa16b9d0edd7f9b5c3f9ade6 Run Images: gcr.io/paketo-buildpacks/run:base-cnb Buildpacks: ID VERSION paketo-buildpacks/bellsoft-liberica 2.5.3 paketo-buildpacks/executable-jar 1.2.3 paketo-buildpacks/apache-tomcat 1.1.3 paketo-buildpacks/dist-zip 1.3.0 paketo-buildpacks/spring-boot 1.5.3 Processes: TYPE SHELL COMMAND ARGS web (default) bash java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher executable-jar bash java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher task bash java -cp "${CLASSPATH}" ${JAVA_OPTS} org.springframework.boot.loader.JarLauncher ``` ### イメージの実行 作成したイメージを`docker run`で起動します。 ``` docker run --rm -p 8080:8080 making/pack-spring-boot ``` 起動時に次のようなログが出力されます。 ``` Container memory limit unset. Configuring JVM for 1G container. Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=86460K -XX:ReservedCodeCacheSize=240M -Xss1M -Xmx450115K (Head Room: 0%, Loaded Class Count: 12851, Thread Count: 250, Total Memory: 1073741824) . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.6.RELEASE) 2020-04-28 11:48:02.255 INFO 1 --- [ main] hello.HelloSpringBootApplication : Starting HelloSpringBootApplication on 89d27837109d with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace) 2020-04-28 11:48:02.269 INFO 1 --- [ main] hello.HelloSpringBootApplication : No active profile set, falling back to default profiles: default 2020-04-28 11:48:03.870 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080 2020-04-28 11:48:03.876 INFO 1 --- [ main] hello.HelloSpringBootApplication : Started HelloSpringBootApplication in 2.197 seconds (JVM running for 2.776) ``` JVMのメモリが自動で設定されていることに注目してください。 アプリケーションにアクセスします。 ``` $ curl localhost:8080 -w '\n' Hello World! ``` Docker Imageのサイズを確認します。 ``` $ docker images | grep making/pack-spring-boot making/pack-spring-boot latest 700844feaf57 40 years ago 260MB ``` Java Buildpackの細かい設定は https://github.com/paketo-buildpacks/java を確認してください。 おわったらDocker Imageを削除します。 ``` docker rmi making/pack-spring-boot ```