Speeding up the launch of Spring Boot applications in a container

Did you know that a Spring Boot application in a container can launch in milliseconds? At the same time, without compromising performance, memory, parity of development-production environments, without limiting the capabilities of the Java language, and almost without changing the application code. But how? Using Liberty 23.0.0.10-beta…

Liberty Instant On

Open Liberty’s InstantOn functionality uses IBM Semeru JDK and Linux technology Checkpoint/Restore in Userspace (CRIU), which allows you to take snapshots of the process state (snapshots, checkpoints) during execution. Subsequently, the condition is very quickly restored and work resumes. You can restore an application multiple times because Open Liberty and Semeru JDK preserve the uniqueness of each restored process in the container. Once the state is restored, the process does not need to initialize at startup, saving up to 90% of startup time (depending on your application). Using InstantOn requires minor changes to your Java application.

For more information about Liberty InstantOn, see the article How to package your cloud-native Java application for rapid startup and in the section Faster startup for containerized applications with Open Liberty InstantOn Open Liberty documentation.

Checkpoint/restore support in Spring Boot

Spring Framework 6.1 will integrate with JVM checkpoint/restore using the project org.crac, which will speed up the launch of applications. In Liberty InstantOn version 23.0.0.10-beta to get the implementation org.crac API you need to add the functional module (feature) crac-1.3. This will allow you to deploy Spring applications, including Spring Boot, using Liberty InstantOn.

Production-ready images of Liberty containers

Container images for all new Liberty releases are created based on Universal Base Image and uploaded to the repository IBM Container Registry. The Liberty UBI image as of Liberty 23.0.0.6 includes the necessary components to create application checkpoints using Liberty InstantOn. And from version 23.0.0.10-beta – also for Spring Boot 3.2.

Liberty images make it easy to develop InstantOn applications ready for production deployment. An important advantage of Liberty InstantOn is the ability to create application process checkpoints inside a container without the need to run the application in the container as root, which is important from a security point of view. This also allows deploy your InstantOn images in Kubernetes cloud services such as AWS EKS and Azure EKS.

Sample application on Spring Boot 3.2.0 using Liberty InstantOn

This example uses materials from the tutorial Containerizing, packaging, and running a Spring Boot application. The easiest way to get started is to clone the cracSpringBoot branch from the github repository with an example:

git clone --branch cracSpringBoot https://github.com/openliberty/guide-spring-boot.git
cd guide-spring-boot/finish

In the thread cracSpringBoot newer versions of Open Liberty and Spring Boot are used that support org.crac for Spring Boot applications. You will need Java 17 or later.

To build the application, let’s run mvnw in folder finish.

./mvnw package

Next we will containerize our application. We will only focus on the containerization changes associated with Liberty InstantOn. For more information on best practices for containerizing Spring Boot applications with Open Liberty, see the guide Containerizing, packaging, and running a Spring Boot application.

To create an image of an application that uses InstantOn, you must either run a privileged container or provide the image build tool with the necessary Linux capabilitiesallowing you to create control points.

Enabling crac-1.3 in Liberty

At Liberty, we can select only the components we need. For use org.crac in Liberty, you need to add it to the Liberty configuration crac-1.3. In this case, you can copy the file src/main/liberty/config/crac.xml into the container image using the following command in the Dockerfile:

COPY src/main/liberty/config/crac.xml /config/configDropins/defaults

Enable crac-1.3 in the Liberty configuration crac.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<server description="Enable the org.crac API">

    <featureManager>
        <feature>crac-1.3</feature>
    </featureManager>

</server>

Building an image using Podman

Podman allows you, when building an image, to specify the Linux capabilities necessary to create an application checkpoint, which will allow you to run checkpoint.sh using the command RUN in Dockerfile. This is the last instruction in Dockerfile.podman:

...
RUN configure.sh
RUN checkpoint.sh afterAppStart

To build the image, use the following command indicating the required capabilities:

sudo podman build \
  -f Dockerfile.podman \
  -t springboot \
  --cap-add=CHECKPOINT_RESTORE \
  --cap-add=SYS_PTRACE\
  --cap-add=SETPCAP \
  --security-opt seccomp=unconfined .

You can also run the script scripts/build-instanton-podman.sh from examples.

The last stage of image assembly is launch checkpoint.sh with parameter afterAppStart. As a result, a checkpoint is created after the application starts. For other options for creating a control point, see documentation.

When you run the application, you will see the following result:

[AUDIT   ] CWWKZ0001I: Application thin-guide-spring-boot-0.1.0 started in 3.880 seconds.
[AUDIT   ] CWWKC0451I: A server checkpoint "afterAppStart" was requested. When the checkpoint completes, the server stops.
2023-09-06T21:06:18.763Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping Spring-managed lifecycle beans before JVM checkpoint
2023-09-06T21:06:18.767Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 2147483647
2023-09-06T21:06:18.768Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Bean 'applicationTaskExecutor' completed its stop procedure
2023-09-06T21:06:18.769Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 2147482623
2023-09-06T21:06:18.771Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Bean 'webServerGracefulShutdown' completed its stop procedure
2023-09-06T21:06:18.771Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 2147481599
2023-09-06T21:06:18.796Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Bean 'webServerStartStop' completed its stop procedure
2023-09-06T21:06:18.796Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase -2147483647
2023-09-06T21:06:18.797Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Bean 'springBootLoggingLifecycle' completed its stop procedure
[2/2] COMMIT springboot

The logs show that the application was stopped to create a checkpoint. You now have an application container image called springboot.

Building an image using Docker

Currently, Docker does not allow you to specify Linux capabilities. For this reason we cannot run checkpoint.sh by doing docker build. Instead we will use three-stage image build:

  1. Let’s assemble the image without the InstantOn layer.

  2. Let’s launch a container from the resulting image and create an application checkpoint.

  3. Let’s save the container with the checkpoint into a new InstantOn image using commit.

Complete these three build steps by running the script scripts/build-instanton-docker.sh. The output when building via Docker is similar to that of Podman. In the log you will see messages from lifecycle beans.

Launching the application

Both Podman and Docker use the same startup options:

Files run-instanton-podman.sh And run-instanton-docker.sh:

[sudo podman or docker] run \
  --rm \
  -p 9080:9080 \
  --cap-add=CHECKPOINT_RESTORE \
  --cap-add=SETPCAP \
  --security-opt seccomp=unconfined \
  springboot

To start, you can use this command or one of the scripts: scripts/run-instanton-podman.sh or scripts/run-instanton-docker.sh.

When you run it, you will see the following output:

[AUDIT   ] Launching defaultServer (Open Liberty 23.0.0.10-beta/wlp-1.0.81.cl230920230904-1158) on Eclipse OpenJ9 VM, version 17.0.7+7 (en_US)
2023-09-07T15:22:52.683Z  INFO 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Restarting Spring-managed lifecycle beans after JVM restore
2023-09-07T15:22:52.684Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase -2147483647
2023-09-07T15:22:52.684Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Successfully started bean 'springBootLoggingLifecycle'
2023-09-07T15:22:52.685Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147481599
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://e93ebe585ce3:9080/
2023-09-07T15:22:52.759Z  INFO 118 --- [ecutor-thread-1] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 106109 ms
2023-09-07T15:22:52.762Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Successfully started bean 'webServerStartStop'
2023-09-07T15:22:52.763Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147482623
2023-09-07T15:22:52.763Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Successfully started bean 'webServerGracefulShutdown'
2023-09-07T15:22:52.763Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2023-09-07T15:22:52.763Z DEBUG 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Successfully started bean 'applicationTaskExecutor'
2023-09-07T15:22:52.764Z  INFO 118 --- [ecutor-thread-1] o.s.c.support.DefaultLifecycleProcessor  : Spring-managed lifecycle restart completed in 80 ms
[AUDIT   ] CWWKC0452I: The Liberty server process resumed operation from a checkpoint in 0.263 seconds.
[AUDIT   ] CWWKZ0001I: Application thin-guide-spring-boot-0.1.0 started in 0.265 seconds.
[AUDIT   ] CWWKF0012I: The server installed the following features: [crac-1.3, expressionLanguage-5.0, pages-3.1, servlet-6.0, springBoot-3.0, ssl-1.0, transportSecurity-1.0, websocket-2.1].
[AUDIT   ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 0.277 seconds.

Please note the last message “… server started in 0.277 seconds“. The startup time of 0.277 seconds includes both the time required criu to restore the Java process, and the time required for Liberty to properly restore the runtime state to safely launch the application after restoration. As a result, we received more than ten times faster startup compared to the original 5.5+ seconds. without using InstantOn.

Summary

Open Liberty InstantOn provides a single runtime environment for deploying cloud-native applications with instant startup. Liberty InstantOn can be used with applications that use open standards such as Jakarta EE and MicroProfile, as well as Spring applications that use the latest versions of Spring Boot and the Spring Framework that support org.crac.

Open Liberty has the following advantages:

  • Access the full Java SE platform without any compromises. To launch quickly, there is no need to change the application code to suit the environment, as, for example, with native compilation.

  • Optimized Liberty runtime provides high performance and uses less memory compared to other runtimes.

  • Enhanced JIT compilation capabilities for cloud deployments (Semeru Cloud Compiler).

  • Run in a runtime environment that contains only the required components, allowing you to reduce the size of the container image.

  • Using production-ready Open Liberty images allows you to adhere to best practices for container optimization and security, such as not running the application in the container as root and avoiding privileged containers.

InstantOn application images are ready for deployment in public clouds such as AWS EKS and Azure AKS. The fast startup time provided by Liberty InstantOn makes it an ideal platform for building serverless applications, including those based on SpringBoot.

In conclusion, we invite everyone to the open lesson “Development of REST clients in Spring”, which will be held on November 14. You can sign up on the Spring course page.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *