{"id":16179164,"url":"https://github.com/jonashackt/spring-boot-buildpack","last_synced_at":"2025-03-16T10:31:31.529Z","repository":{"id":38419304,"uuid":"307666346","full_name":"jonashackt/spring-boot-buildpack","owner":"jonashackt","description":"Example project showing how to use Buildpacks.io together with Spring Boot \u0026 it's layered jar feature","archived":false,"fork":false,"pushed_at":"2025-03-10T11:26:19.000Z","size":2444,"stargazers_count":33,"open_issues_count":7,"forks_count":9,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-10T12:29:52.347Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonashackt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-27T10:41:08.000Z","updated_at":"2024-10-30T20:06:52.000Z","dependencies_parsed_at":"2024-01-20T00:24:03.943Z","dependency_job_id":"d8d7554a-cbaa-4094-a3a9-51c672aa325c","html_url":"https://github.com/jonashackt/spring-boot-buildpack","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-buildpack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-buildpack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-buildpack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-buildpack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonashackt","download_url":"https://codeload.github.com/jonashackt/spring-boot-buildpack/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243814895,"owners_count":20352036,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T05:25:41.668Z","updated_at":"2025-03-16T10:31:31.137Z","avatar_url":"https://github.com/jonashackt.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spring-boot-buildpack\n\n[![Build Status](https://github.com/jonashackt/spring-boot-buildpack/workflows/build/badge.svg)](https://github.com/jonashackt/spring-boot-buildpack/actions)\n[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/jonashackt/spring-boot-buildpack/blob/master/LICENSE)\n[![renovateenabled](https://img.shields.io/badge/renovate-enabled-yellow)](https://renovatebot.com)\n[![versionspringboot](https://img.shields.io/badge/dynamic/xml?color=brightgreen\u0026url=https://raw.githubusercontent.com/jonashackt/spring-boot-buildpack/main/pom.xml\u0026query=%2F%2A%5Blocal-name%28%29%3D%27project%27%5D%2F%2A%5Blocal-name%28%29%3D%27parent%27%5D%2F%2A%5Blocal-name%28%29%3D%27version%27%5D\u0026label=springboot)](https://github.com/spring-projects/spring-boot)\n[![Pushed to Docker Hub](https://img.shields.io/badge/docker_hub-released-blue.svg?logo=docker)](https://hub.docker.com/r/jonashackt/spring-boot-buildpack)\n\nExample project showing how to use Buildpacks.io together with Spring Boot \u0026amp; it's layered jar feature\n\n[![asciicast](https://asciinema.org/a/368329.svg)](https://asciinema.org/a/368329)\n\nI was really inspired to get to know the concept of buildpacks after attending this year's Spring One 2020 - and especially the talk by https://twitter.com/nebhale : https://www.youtube.com/watch?v=44n_MtsggnI\n\n## Table of Contents \n\n* [Spring Boot \u0026 Cloud Native Build Packs?](#spring-boot--cloud-native-build-packs)\n* [Step by step...](#step-by-step)\n* [\"dive\" into the Containers](#dive-into-the-containers)\n* [Paketo pack CLI](#paketo-pack-cli)\n  * [Why are the Spring Boot \u0026 Paketo images 40 years old?](#why-are-the-spring-boot--paketo-images-40-years-old)\n* [Layered jars](#layered-jars)\n* [Using Layered jars inside Dockerfiles](#using-layered-jars-inside-dockerfiles)\n* [Buildpacks with layered jars](#buildpacks-with-layered-jars)\n* [Doing a Buildpack build on TravisCI](#doing-a-buildpack-build-on-travisci)\n\n\n\n### Spring Boot \u0026 Cloud Native Build Packs?\n\n__Buildpacks?__\n\n* Heroku invented (2011)\n\n\u003e Buildpacks were first conceived by Heroku in 2011. Since then, they have been adopted by Cloud Foundry (Pivotal) and other PaaS such as Google App Engine, Gitlab, Knative, Deis, Dokku, and Drie.\n\n__Cloud Native Buildpacks \u0026 Paketo__\n\n* today: [CNCF Incubation project](https://www.cncf.io/blog/2020/11/18/toc-approves-cloud-native-buildpacks-from-sandbox-to-incubation/) \n\n\u003e Specification for turning applications into Docker images: [buildpacks.io](https://buildpacks.io/)\n\nPaketo.io is an implementation for major languages (Java, Go, .Net, node.js, Ruby, PHP...)\n--\u003e [paketo.io](https://paketo.io/)\n\nSimilar to tools like: Jib https://github.com/GoogleContainerTools/jib, ko https://github.com/google/ko, Bazel (https://bazel.build/)\n\n__Maven/Gradle Plugin to use Paketo Buildpacks__\n\nThe build-image plugin takes care of doing the Paketo build. From Spring Boot 2.3.x on simply run it with:\n\n```shell script\nmvn spring-boot:build-image\n```\n\n\n\n### Step by step...\n\nAlways start at [start.spring.io](start.spring.io) :)\n\n![start-spring-io](screenshots/start-spring-io.png)\n\nImplement your App (e.g. building a reactive Web app using Spring Webflux).\n\nThen run the build with:\n\n```shell script\nmvn spring-boot:build-image\n```\n\nThis will do a \"normal\" Maven build of your Spring Boot app, but also be \n\n```shell script\n$ mvn spring-boot:build-image\n...\n[INFO] --- spring-boot-maven-plugin:2.4.0-M4:build-image (default-cli) @ spring-boot-buildpack ---\n[INFO] Building image 'docker.io/library/spring-boot-buildpack:0.0.1-SNAPSHOT'\n[INFO]\n[INFO]  \u003e Pulling builder image 'docker.io/paketobuildpacks/builder:base' 100%\n[INFO]  \u003e Pulled builder image 'paketobuildpacks/builder@sha256:00a9c25f8f994c1a044fa772f7e9314fe5d90d329b40f51426e1dafadbfa5ac8'\n[INFO]  \u003e Pulling run image 'docker.io/paketobuildpacks/run:base-cnb' 100%\n[INFO]  \u003e Pulled run image 'paketobuildpacks/run@sha256:21c1fb65033ae5a765a1fb44bfefdea37024ceac86ac6098202b891d27b8671f'\n[INFO]  \u003e Executing lifecycle version v0.9.2\n[INFO]  \u003e Using build cache volume 'pack-cache-604f3372716a.build'\n[INFO]\n[INFO]  \u003e Running creator\n[INFO]     [creator]     ===\u003e DETECTING\n[INFO]     [creator]     5 of 17 buildpacks participating\n[INFO]     [creator]     paketo-buildpacks/bellsoft-liberica 4.0.0\n[INFO]     [creator]     paketo-buildpacks/executable-jar    3.1.1\n[INFO]     [creator]     paketo-buildpacks/apache-tomcat     2.3.0\n[INFO]     [creator]     paketo-buildpacks/dist-zip          2.2.0\n[INFO]     [creator]     paketo-buildpacks/spring-boot       3.2.1\n[INFO]     [creator]     ===\u003e ANALYZING\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:jre\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:jvmkill\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:helper\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:java-security-properties\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/executable-jar:class-path\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/spring-boot:spring-cloud-bindings\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/spring-boot:web-application-type\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/spring-boot:helper\" from app image\n[INFO]     [creator]     ===\u003e RESTORING\n[INFO]     [creator]     ===\u003e BUILDING\n[INFO]     [creator]\n[INFO]     [creator]     Paketo BellSoft Liberica Buildpack 4.0.0\n[INFO]     [creator]       https://github.com/paketo-buildpacks/bellsoft-liberica\n[INFO]     [creator]       Build Configuration:\n[INFO]     [creator]         $BP_JVM_VERSION              11.*            the Java version\n[INFO]     [creator]       Launch Configuration:\n[INFO]     [creator]         $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation\n[INFO]     [creator]         $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation\n[INFO]     [creator]         $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation\n[INFO]     [creator]         $JAVA_TOOL_OPTIONS                           the JVM launch flags\n[INFO]     [creator]       BellSoft Liberica JRE 11.0.8: Reusing cached layer\n[INFO]     [creator]       Launch Helper: Reusing cached layer\n[INFO]     [creator]       JVMKill Agent 1.16.0: Reusing cached layer\n[INFO]     [creator]       Java Security Properties: Reusing cached layer\n[INFO]     [creator]\n[INFO]     [creator]     Paketo Executable JAR Buildpack 3.1.1\n[INFO]     [creator]       https://github.com/paketo-buildpacks/executable-jar\n[INFO]     [creator]       Process types:\n[INFO]     [creator]         executable-jar: java org.springframework.boot.loader.JarLauncher\n[INFO]     [creator]         task:           java org.springframework.boot.loader.JarLauncher\n[INFO]     [creator]         web:            java org.springframework.boot.loader.JarLauncher\n[INFO]     [creator]\n[INFO]     [creator]     Paketo Spring Boot Buildpack 3.2.1\n[INFO]     [creator]       https://github.com/paketo-buildpacks/spring-boot\n[INFO]     [creator]       Creating slices from layers index\n[INFO]     [creator]         dependencies\n[INFO]     [creator]         spring-boot-loader\n[INFO]     [creator]         snapshot-dependencies\n[INFO]     [creator]         application\n[INFO]     [creator]       Launch Helper: Reusing cached layer\n[INFO]     [creator]       Web Application Type: Reusing cached layer\n[INFO]     [creator]       Spring Cloud Bindings 1.6.0: Reusing cached layer\n[INFO]     [creator]       4 application slices\n[INFO]     [creator]       Image labels:\n[INFO]     [creator]         org.opencontainers.image.title\n[INFO]     [creator]         org.opencontainers.image.version\n[INFO]     [creator]         org.springframework.boot.spring-configuration-metadata.json\n[INFO]     [creator]         org.springframework.boot.version\n[INFO]     [creator]     ===\u003e EXPORTING\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:helper'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:jre'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/bellsoft-liberica:jvmkill'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/executable-jar:class-path'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/spring-boot:helper'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'\n[INFO]     [creator]     Reusing layer 'paketo-buildpacks/spring-boot:web-application-type'\n[INFO]     [creator]     Reusing 5/5 app layer(s)\n[INFO]     [creator]     Reusing layer 'launcher'\n[INFO]     [creator]     Reusing layer 'config'\n[INFO]     [creator]     Adding label 'io.buildpacks.lifecycle.metadata'\n[INFO]     [creator]     Adding label 'io.buildpacks.build.metadata'\n[INFO]     [creator]     Adding label 'io.buildpacks.project.metadata'\n[INFO]     [creator]     Adding label 'org.opencontainers.image.title'\n[INFO]     [creator]     Adding label 'org.opencontainers.image.version'\n[INFO]     [creator]     Adding label 'org.springframework.boot.spring-configuration-metadata.json'\n[INFO]     [creator]     Adding label 'org.springframework.boot.version'\n[INFO]     [creator]     *** Images (408f3d59f38e):\n[INFO]     [creator]           docker.io/library/spring-boot-buildpack:0.0.1-SNAPSHOT\n[INFO]\n[INFO] Successfully built image 'docker.io/library/spring-boot-buildpack:0.0.1-SNAPSHOT'\n[INFO]\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  20.009 s\n[INFO] Finished at: 2020-10-27T14:29:46+01:00\n[INFO] ------------------------------------------------------------------------\n``` \n\nAs you can see in the first phases `DETECTING` and `ANALYZING`, the build process analyses the given application and identifies multiple build packs that are needed to successfully package the application into a Docker image:\n\n```\n[INFO]     [creator]     ===\u003e ANALYZING\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:jre\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:jvmkill\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:helper\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/bellsoft-liberica:java-security-properties\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/executable-jar:class-path\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/spring-boot:spring-cloud-bindings\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/spring-boot:web-application-type\" from app image\n[INFO]     [creator]     Restoring metadata for \"paketo-buildpacks/spring-boot:helper\" from app image\n```\n\nFor example there's `paketo-buildpacks/bellsoft-liberica:jre` to bring in a JRE, since we have a Java app here. And there's also `paketo-buildpacks/executable-jar` since the resulting application is an executable jar.\n\nAlso there are a few `paketo-buildpacks/spring-boot-x` build packs because we have a Spring Boot application.\n \n\nNow simply run your Dockerized app via\n\n```\ndocker run -p 8080:8080 spring-boot-buildpack\n```\n\n\n### \"dive\" into the Containers\n\nLet's use the great Container introspection tool [dive](https://github.com/wagoodman/dive) to gain an insight of the build Docker image\n\nInstall it with `brew install dive` on a Mac (or see https://github.com/wagoodman/dive#installation)\n \nUsing dive we see a whole lot of Docker image layers containing all the different paketo layers:\n\n![dive-container-layers-without-layered-jars-feature](screenshots/dive-container-layers-without-layered-jars-feature.png)\n\nIf you want to have dive always start with the default to hide file attributes \u0026 unmodified files of each layer for an easier overview whats going on inside the layers, you can have a look at\nhttps://github.com/wagoodman/dive#ui-configuration or simply create a `.dive.yaml` inside your home directory. Here's my `.dive.yaml` for convenience:\n\n```yaml\ndiff:\n  # You can change the default files shown in the filetree (right pane). All diff types are shown by default.\n  hide:\n    - unmodified\n\nfiletree:\n  # Show the file attributes next to the filetree\n  show-attributes: false\n```\n\nBtw. it's also the dive configuration https://twitter.com/nebhale uses in his SpringOne 2020 talk - and it took me a while to get that one right :) \n\n\n\n### Paketo pack CLI\n\nUse Paketo without the Maven/Gradle build plugin directly through the CLI.\n\nYou need to [install pack CLI](https://buildpacks.io/docs/tools/pack/#pack-cli) first. On a Mac simply use brew:\n\n```\nbrew install buildpacks/tap/pack\n```\n\nChoose one Paketo builder then\n\n```\n$ pack suggest-builders\n\nSuggested builders:\n\tGoogle:                gcr.io/buildpacks/builder:v1      Ubuntu 18 base image with buildpacks for .NET, Go, Java, Node.js, and Python\n\tHeroku:                heroku/buildpacks:18              heroku-18 base image with buildpacks for Ruby, Java, Node.js, Python, Golang, \u0026 PHP\n\tPaketo Buildpacks:     paketobuildpacks/builder:base     Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang\n\tPaketo Buildpacks:     paketobuildpacks/builder:full     Ubuntu bionic base image with buildpacks for Java, .NET, NodeJS, Golang, PHP, HTTPD and NGINX\n\tPaketo Buildpacks:     paketobuildpacks/builder:tiny     Tiny base image (bionic build image, distroless run image) with buildpacks for Golang\n\nTip: Learn more about a specific builder with:\n\tpack inspect-builder \u003cbuilder-image\u003e\n```\n\n\nDirectly use Paketo with the pack CLI\n\n```\npack build spring-boot-buildpack --path . --builder paketobuildpacks/builder:base\n```\n\nThis will do exactly the same build which was run via the Spring Boot Maven build-image plugin behind the scenes (but maybe in more beautiful color):\n\n[![asciicast](https://asciinema.org/a/368331.svg)](https://asciinema.org/a/368331)\n\nNow simply use Docker to run the resulting image:\n\n```\ndocker run -p 8080:8080 spring-boot-buildpack\n```\n\nand access your app on http://localhost:8080/hello\n\n\n##### Why are the Spring Boot \u0026 Paketo images 40 years old?\n\nAs you may noticed the resulting images have a really old timestamp:\n\n```shell script\ngcr.io/paketo-buildpacks/builder          base-platform-api-0.3   914aba170326        40 years ago        654MB\npaketobuildpacks/builder                  \u003cnone\u003e                  914aba170326        40 years ago        654MB\nspring-boot-buildpack-gcr-builder         latest                  6c7a74899b13        40 years ago        462MB\npack.local/builder/axczkudrjk             latest                  69aeed7ad644        40 years ago        654MB\nspring-boot-buildpack                     latest                  b529a37599a6        40 years ago        259MB\njonashackt/spring-boot-buildpack          latest                  a9ccbb57fffd        40 years ago        259MB\npaketobuildpacks/builder                  base                    1435430a71b7        40 years ago        558MB\n```\n\nWhy is that? Because of providing reproducible builds (see this https://reproducible-builds.org/ for more info).\n\nThere's great post about the why available here: https://medium.com/buildpacks/time-travel-with-pack-e0efd8bf05db (Thanks coldfinger [to clarify this one on stackoverflow](https://stackoverflow.com/a/62866908/4964553)!)\n\nLong story short: Without the fixed timestamp the hashes of the Docker images would differ every time you would issue a build (although maybe only seconds) - and then it wouldn't be clear, if anything changed.\n\n\n\n### Layered jars\n\nFrom Spring Boot 2.3 on there's also [a build in feature called layered jars](https://spring.io/blog/2020/08/14/creating-efficient-docker-images-with-spring-boot-2-3).\n\nBefore looking into the layered jars featuer, we should bring a standard Spring Boot jar layout to our minds. Simply unzip `spring-boot-buildpack-0.0.1-SNAPSHOT.jar` to see what's inside:\n\n![jar-layout](screenshots/jar-layout.png)\n\nYou can see `BOOT-INF`, `META-INF` and `org` directories - where `BOOT-INF/classes` contains our application classes and `BOOT-INF/lib` inherits all application dependencies. The directory `org/springframework/boot/loader` contains all Spring Boot magic classes that are needed to create the executable Boot app. So nothing new here for the moment.\n\n[While using Spring Boot 2.3.x we need activate this feature](https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/maven-plugin/reference/html/#repackage-layers) with simply configuring our `spring-boot-maven-plugin`:\n\n```\n\t\u003cbuild\u003e\n\t\t\u003cplugins\u003e\n\t\t\t\u003cplugin\u003e\n\t\t\t\t\u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n\t\t\t\t\u003cartifactId\u003espring-boot-maven-plugin\u003c/artifactId\u003e\n\t\t\t\t\u003cconfiguration\u003e\n\t\t\t\t\t\u003clayers\u003e\n\t\t\t\t\t\t\u003cenabled\u003etrue\u003c/enabled\u003e\n\t\t\t\t\t\u003c/layers\u003e\n\t\t\t\t\u003c/configuration\u003e\n\t\t\t\u003c/plugin\u003e\n\t\t\u003c/plugins\u003e\n\t\u003c/build\u003e\n```\n\n[From Spring Boot 2.4.x Milestones (and GA) on, you don't even need to configure it since the default behavior then](https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/maven-plugin/reference/html/#repackage-layers):\n\n\u003e The repackaged jar includes the layers.idx file by default.\n\n\nNow run a fresh \n\n```\nmvn clean package\n```\n\nNow our jar file's `BOOT-INF` directory contains a new `layers.idx` file:\n\n```\n- \"dependencies\":\n  - \"BOOT-INF/lib/\"\n- \"spring-boot-loader\":\n  - \"org/\"\n- \"snapshot-dependencies\":\n- \"application\":\n  - \"BOOT-INF/classes/\"\n  - \"BOOT-INF/classpath.idx\"\n  - \"BOOT-INF/layers.idx\"\n  - \"META-INF/\"\n```\n\nAs you can see the main thing about this is to assign our directories to layers and implement an order for them! Our dependencies define the first layer since they are likely to not change that often.\n\nThe second layer inherits all Spring Boot loader classes and also shouldn't change all too much. Our SNAPSHOT dependencies then make for a more variable part and create the 3rd layer.\n\nFinally our application's class files and so on are likely to change a lot! So they reside in the last layer.\n\nIn order to view the layers, there's a new command line option (or system property) `-Djarmode=layertools` for us. Simply `cd` into the `target` directory and run:\n\n```\n$ java -Djarmode=layertools -jar spring-boot-buildpack-0.0.1-SNAPSHOT.jar list\n\ndependencies\nspring-boot-loader\nsnapshot-dependencies\napplication\n```\n\nTo extract each layer, we can also use the command line option with the `extract` option:\n\n```\n$ java -Djarmode=layertools -jar spring-boot-buildpack-0.0.1-SNAPSHOT.jar extract\n```\n\nNow inside the `target` directory you should find 4 more folders, which represent the separate layers:\n\n![extracted-jar-layers](screenshots/extracted-jar-layers.png)\n\n\n### Using Layered jars inside Dockerfiles\n\nAll those directories could be used to create a separate layer inside a Docker image e.g. by using the `COPY` command. Phil Webb [outlined this in his spring.io post](https://spring.io/blog/2020/01/27/creating-docker-images-with-spring-boot-2-3-0-m1) already, where he crafts a `Dockerfile` that runs the `java -Djarmode=layertools -jar` command in the first build container and then uses the extracted directories to create seperate Docker layers from them: \n\n```dockerfile\nFROM adoptopenjdk:11-jre-hotspot as builder\nWORKDIR application\nARG JAR_FILE=target/*.jar\nCOPY ${JAR_FILE} application.jar\nRUN java -Djarmode=layertools -jar application.jar extract\n\nFROM adoptopenjdk:11-jre-hotspot\nWORKDIR application\nCOPY --from=builder application/dependencies/ ./\nCOPY --from=builder application/spring-boot-loader/ ./\nCOPY --from=builder application/snapshot-dependencies/ ./\nCOPY --from=builder application/application/ ./\nENTRYPOINT [\"java\", \"org.springframework.boot.loader.JarLauncher\"]\n```\n\nYou can run the Docker build if you want using the [DockerfileThatsNotNeededUsingBuildpacks](DockerfileThatsNotNeededUsingBuildpacks) via:\n\n```\ndocker build . --tag spring-boot-layered --file DockerfileThatsNotNeededUsingBuildpack\n```\n\nAnd inside the output you'll see the separate layers beeing created:\n\n```\n...\nStep 8/12 : COPY --from=builder application/dependencies/ ./\n ---\u003e 88bb8adaaca6\nStep 9/12 : COPY --from=builder application/spring-boot-loader/ ./\n ---\u003e 3922891db128\nStep 10/12 : COPY --from=builder application/snapshot-dependencies/ ./\n ---\u003e f139bcf5babb\nStep 11/12 : COPY --from=builder application/application/ ./\n ---\u003e 5d02393d4fe2\n...\n```\n\nWe can even further examine the created Docker image with `dive`:\n\n```\ndive spring-boot-layered\n```\n\nIt was really cool for me to see that one in action!\n\n![dive-docker-image-with-layeres](screenshots/dive-docker-image-with-layeres.png)\n\n\n### Buildpacks with layered jars\n\nNow running our build pack powered Maven build again should show a new part `Creating slices from layers index` inside the `Paketo Spring Boot Buildpack` output:\n\n```\n$ mvn spring-boot:build-image\n...\n[INFO]     [creator]     Paketo Spring Boot Buildpack 3.2.1\n[INFO]     [creator]       https://github.com/paketo-buildpacks/spring-boot\n[INFO]     [creator]       Creating slices from layers index\n[INFO]     [creator]         dependencies\n[INFO]     [creator]         spring-boot-loader\n[INFO]     [creator]         snapshot-dependencies\n[INFO]     [creator]         application\n[INFO]     [creator]       Launch Helper: Reusing cached layer\n...\n```\n\n\u003e Oh, I found a bug https://github.com/paketo-buildpacks/spring-boot/issues/1 , which comes from a change in the buildpacks/lifecycle umbrella project: https://github.com/buildpacks/lifecycle/issues/455\n\nBug was fixed already :) So we could move on! After doing our build pack powered build, at the end of the log you should find the latest image id like `*** Images (4c26dc7b3fa3)`:\n\n```\n...\n*** Images (4c26dc7b3fa3):\n      spring-boot-buildpack\nReusing cache layer 'paketo-buildpacks/bellsoft-liberica:jdk'\nAdding cache layer 'paketo-buildpacks/maven:application'\nAdding cache layer 'paketo-buildpacks/maven:cache'\nReusing cache layer 'paketo-buildpacks/maven:maven'\nSuccessfully built image spring-boot-buildpack\n```\n\nNow let's dive into the build image and watch our for our layers inside it:\n\n![dive-container-layers-paketo-using-layered-jars-feature](screenshots/dive-container-layers-paketo-using-layered-jars-feature.png)\n\n\n\n### Doing a Buildpack build on TravisCI\n\nLet's have a look into this project's [.travis.yml](.travis.yml):\n\n```yaml\nlanguage: java\n\njdk:\n  - openjdk11\n\ncache:\n  directories:\n    - $HOME/.m2\n\nservices:\n  - docker\n\njobs:\n  include:\n    - script:\n        - mvn clean spring-boot:build-image\n\n      name: \"Build Spring Boot app with build-image Maven plugin\"\n\n    - script:\n        # Install pack CLI via homebrew. See https://buildpacks.io/docs/tools/pack/#pack-cli\n        - (curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.14.2/pack-v0.14.2-linux.tgz\" | sudo tar -C /usr/local/bin/ --no-same-owner -xzv pack)\n\n        # Build app with pack CLI\n        - pack build spring-boot-buildpack --path . --builder paketobuildpacks/builder:base\n\n        # Push to Docker Hub also\n        - echo \"$DOCKER_HUB_TOKEN\" | docker login -u \"$DOCKER_HUB_USERNAME\" --password-stdin\n        - docker tag spring-boot-buildpack jonashackt/spring-boot-buildpack:latest\n        - docker push jonashackt/spring-boot-buildpack:latest\n\n      name: \"Build Spring Boot app with Paketo.io pack CLI\"\n```\n\nI wanted to have both possible build options covered - the first uses the Maven plugin with `mvn clean spring-boot:build-image`.\n\nThe second installs `pack CLI` and build the application using it. Also the resulting image is pushed to DockerHub at https://hub.docker.com/r/jonashackt/spring-boot-buildpack\n\n\n### Building GraalVM Native Images from Spring Boot Apps using Buildpacks\n\nThere's a new Maven goal in town to use Buildpacks to create Native Images (see https://github.com/jonashackt/spring-boot-graalvm)\n\n```shell script\nmvn springboot:native\n```\n\n\n### Links\n\nSpring One 2020 talk by https://twitter.com/nebhale : https://www.youtube.com/watch?v=44n_MtsggnI\n\nhttps://spring.io/blog/2020/01/27/creating-docker-images-with-spring-boot-2-3-0-m1\n\nhttps://spring.io/blog/2020/08/14/creating-efficient-docker-images-with-spring-boot-2-3\n\nhttps://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/maven-plugin/reference/html/#repackage-layers\n\nhttps://www.baeldung.com/spring-boot-docker-images\n\nhttps://github.com/paketo-buildpacks/spring-boot\n\nPackCLI needs Docker container runtime locally, not `docker build`! Build is done by lifecycle, see https://github.com/buildpacks/pack/issues/564#issuecomment-610172880\n\nhttps://www.redhat.com/en/blog/why-red-hat-investing-cri-o-and-podman\n\n\n## Advanced Topics\n\n#### Passing Runtime Environment Variables JAVA_TOOL_OPTS\n\nhttps://stackoverflow.com/questions/64964709/how-to-pass-flags-to-java-process-in-docker-contatiner-built-by-cloud-native-bui/65142031#65142031\n\n\n#### Bindings\n\nConfigure JDK uri of the bellsoft-liberica buildpack:\n\nhttps://stackoverflow.com/questions/65212231/cloud-native-buildpacks-paketo-with-java-spring-boot-how-to-configure-different\n\nConfigure uri of spring-cloud-bindings jar:\n\nhttps://stackoverflow.com/questions/65118519/spring-boot-gradle-bootbuildimage-task-with-private-repo\n\nBindings with spring-boot-maven-plugin\n\nhttps://stackoverflow.com/questions/65078636/how-to-configure-buildpack-bindings-with-the-spring-boot-maven-plugin/65195715#65195715\n\n\n#### Change \n\n\n#### K8s\n\nSkaffold: https://skaffold.dev/docs/pipeline-stages/builders/buildpacks/\n\nhttps://stackoverflow.com/questions/64843991/how-do-i-use-spring-boot-maven-plugin-build-image-with-skaffold-and-dekorate\n\n\n#### Buildpacks with Spring Boot \u003c 2.3\n\nhttps://stackoverflow.com/questions/64061096/using-cloud-native-buildpacks-with-spring-boot-2-3/65142343#65142343\n\n\n\n#### Azure\n\nhttps://docs.microsoft.com/en-us/azure/container-registry/container-registry-tasks-pack-build\n\n\n#### Google Cloud\n\nhttps://cloud.google.com/blog/products/containers-kubernetes/google-cloud-now-supports-buildpacks\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashackt%2Fspring-boot-buildpack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonashackt%2Fspring-boot-buildpack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashackt%2Fspring-boot-buildpack/lists"}