HOWTO: Natively Compile a Spring Boot Application
Notice Information in this article applies to Excelsior JET version 15.3 and above. For versions 11.0 through 15.0, see article #38.
APPLICABILITY
The instructions laid out in this article were validated against Spring Boot 2.0.1 and Docker Engine 18.06.1-ce. They may not fully apply to other versions.
Excelsior JET, Enterprise Edition and Excelsior JET Embedded provide dedicated support for Spring Boot 1.4 and above. Native compilation of Spring Boot application using other Excelsior JET editions and versions is also possible and is covered in this article, though versions prior to 15.3 have weaker support for the Spring framework itself.
SUMMARY
Spring Boot is a framework that facilitates rapid development of Spring-based applications. It is often used to create microservices. The Spring Boot build process normally yields an "uberjar" that can be launched as a standalone application, but it is also possible to produce an executable war file that can be either launched as a standalone application or deployed to a servlet container.
This article provides instructions for compiling a Spring Boot application down to a native executable with Excelsior JET and containerizing it with Docker.
DETAILS
Native Compilation
If you are building your Spring Boot project using Maven or Gradle and the result is an executable jar or war file, then the easiest way to enable native compilation is via dedicated support for Spring Boot found in the respective Excelsior JET plugin: Excelsior JET Maven plugin or Excelsior JET Gradle plugin.
Note that dedicated support for Spring Boot is available only in Excelsior JET, Enterprise Edition and Excelsior JET Embedded. However, a Spring Boot application can also be launched as a plain Java SE application, if you list all its dependencies on the classpath instead of packaging them together with application classes into a single, self-contained executable jar. That means you can actually use any Excelsior JET version and edition to enable the native build, albeit with some extra efforts:
If you have the Spring Boot Maven or Gradle plugin enabled in your
pom.xml
file orbuild.gradle
script, you need to instruct it to not overwrite the application jar file produced by default. (That file contains only your application classes and not their dependencies). You can do that by setting theclassifier
Spring Boot plugin parameter so that your build will produce two jars, or simply disabling the Spring Boot plugin.Important: There is a slight chance that the behavior of your application will depend on whether it is packaged together with all dependencies into a single jar or not. Make sure to test your application built in this mode on a regular JVM before compiling it with Excelsior JET.
Then you can use the Excelsior JET Maven or Gradle plugin with the
appType
parameter plugin"plain"
and themainClass
parameter set to the name of the Spring Boot start class. You may also need to set themainJar
plugin parameter to refer to the jar file containing your application classes.
Containerizing With Docker
Create files Dockerfile
and .dockerignore
in the root directory of your project, replacing my-app-binary
with the actual name of the native binary produced by Excelsior JET:
If using Maven:
Dockerfile
:FROM frolvlad/alpine-glibc:alpine-3.4 COPY target/jet/app . CMD ./my-app-binary EXPOSE 8080
.dockerignore
:src/* target/* !target/jet/app pom.xml .git .gitignore
If using Gradle:
Dockerfile
:FROM frolvlad/alpine-glibc:alpine-3.4 COPY build/jet/app . CMD ./my-app-binary EXPOSE 8080
.dockerignore
:.gradle build/* gradle src/* !build/jet/app build.gradle gradlew gradlew.build .git .gitignore
Important: If you are using a version control system other than Git, make sure to replace the last two lines of .dockerignore
with patterns to exclude the respective files and directories.
Issue a docker build
command to create a Docker image with the application:
docker build -t my-app .
To create a writeable container layer over the freshly created image and start it, issue the following command:
# Change port numbers in the `-p` option as necessary.
docker run -d --name my-service -p 8080:8080 my-app
To check whether the application has started successfully:
docker logs my-service
To stop the container:
docker-compose stop -t 1 my-service
For details, refer to the official Docker documentation.
REFERENCES
Article ID: 42
Last Revised On: 06-Nov-2018