Alpaquita Containers with Alpaquita Linux, Liberica JDK, and support for the Coordinated Restore at Checkpoint (CRaC) offer the developers the “plug-and-play” experience with the OpenJDK CRaC API. Without the need to adjust the JDK or OS, they can conveniently perform the checkpoint and restore the warmed up state of their containerized Java workloads.
This article will guide you through using CRaC with Spring Boot applications running in a Docker container.
Table of Contents
Prerequisites
- Alpaquita Containers with CRaC support (You can download containers with CRaC on our Docker Hub repository under the ‘crac’ tag)
- Spring Boot 3.2+
- Docker
Prepare a Spring Boot app with CRaC
For our tutorial, we will use a Spring Boot reference application, Spring Petclinic.
First of all, clone the Spring Petclinic's repository:
git clone https://github.com/spring-projects/spring-petclinic.git
To use CRaC with the new Spring Boot and Spring Framework, we need to add the dependency for the org.crac/crac package to pom.xml:
<dependency>
<groupId>org.crac</groupId>
<artifactId>crac</artifactId>
<version>1.4.0</version>
</dependency>
Let's check the difference of our updated pom.xml:
git diff
diff --git a/pom.xml b/pom.xml
index 287a08a..f403155 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,11 @@
</properties>
<dependencies>
+ <dependency>
+ <groupId>org.crac</groupId>
+ <artifactId>crac</artifactId>
+ <version>1.4.0</version>
+ </dependency>
<!-- Spring and Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
Prepare a Dockerfile to checkpoint the application in a container
CRaC enables the developers to save the exact state of a running Java application (together with the information about the heap, JIT-compiled code, and so on).
We will use Docker multi-stage builds functionality to containerize the application and checkpoint the running app in a container.
Copy the following Dockerfile:
FROM bellsoft/liberica-runtime-container:jdk-21-crac-musl as builder
WORKDIR /home/app
ADD spring-petclinic-main /home/app/spring-petclinic-main
RUN cd spring-petclinic-main && ./mvnw -Dmaven.test.skip=true clean package
FROM bellsoft/liberica-runtime-container:jre-21-crac-slim-musl as optimizer
WORKDIR /app
COPY /home/app/spring-petclinic-main/target/spring-petclinic-3.3.0-SNAPSHOT.jar /app/app.jar
RUN java -Djarmode=tools -jar app.jar extract --layers --launcher
FROM bellsoft/liberica-runtime-container:jre-21-crac-slim-musl
# We stay root in a container to use CRaC
VOLUME /tmp
EXPOSE 8080
COPY /app/app/dependencies/ ./
COPY /app/app/spring-boot-loader/ ./
COPY /app/app/snapshot-dependencies/ ./
COPY /app/app/application/ ./
ENTRYPOINT ["java", "-Dspring.context.checkpoint=onRefresh", "-XX:CRaCCheckpointTo=/checkpoint", "-XX:MaxRAMPercentage=80.0", "org.springframework.boot.loader.launch.JarLauncher"]
At the first stage, we build the application.
At the second stage, we make use of Spring Boot layered jars. This functionality enables us to store application classes and dependencies in different layers. Note that we need a special JarLauncher class later to work with layered images.
At the third stage, we run the application and perform the automatic checkpoint using Spring’s -Dspring.context.checkpoint=onRefresh
option to start and immediately exit the application after non-lazy beans have been instantiated and InitializingBean#afterPropertiesSet
callbacks have been invoked.
Containerize and start the application in a Docker container
We use the bellsoft/liberica-runtime-container:jdk-21-crac-musl image to start Petclinic and get the application dump for further restore. Note that BellSoft also provides images with glibc libc.
Another important prerequisite is the kernel version of the underlying Linux distribution, which should be at least 5.9. Linux kernel 5.9 introduces the CAP_CHECKPOINT_RESTORE option, which separates the checkpoint/restore functionality from the CAP_SYS_ADMIN option and enables the developers to steer clear of running containers with elevated permissions.
The CAP_CHECKPOINT_RESTORE (and SYS_PTRACE, which is also required for checkpoint-restore) options are enabled with the --cap-add flag added to newer Docker versions, so make sure you have the latest available Docker version.
Use the following command to build a Docker container:
$ docker build . -t petclinic-advanced-crac-checkpoint -f Dockerfile-advanced-crac
Now, let’s run the application in a container.
If you use a Linux distribution with an older kernel version, you can use the --priviledged flag instead of CAP_CHECKPOINT_RESTORE and SYS_PTRACE (however, this is not the best practice to run containers with elevated permissions).
docker run --cap-add CHECKPOINT_RESTORE --cap-add SYS_PTRACE --name petclinic-crac petclinic-advanced-crac-checkpoint
Note that there’s no --rm
option as we'll remove the container manually later.
After that, the application will be automatically stopped and checkpointed.
Transfer the checkpointed app to a new container
Let’s create a fresh image with the checkpointed application:
$ docker commit --change='ENTRYPOINT ["java", "-XX:CRaCRestoreFrom=/checkpoint"]' petclinic-crac petclinic-advanced-crac-restore
Now, remove the previous container manually:
$ docker rm -f petclinic-crac
You can now start the application by restoring it:
$ docker run -it --rm -p 8080:8080 --cap-add CHECKPOINT_RESTORE --cap-add SYS_PTRACE --name petclinic-crac petclinic-advanced-crac-restore
Please note that the -p 8080:8080
option is added to expose the port for the running application.
It is also possible to start other Petclinic instances in separate containers — just use another port on the host system and another container name.
To verify that the app is working correctly, open http://localhost:8080. If there are other instances started, you can open Spring Petclinic using a different port, for example, http://localhost:8081 if the port is opened as in the previous command.
Conclusion
As you can see, CRaC API can be conveniently used with your containerized workloads thanks to ready-to-use Alpaquita Containers.
If you have any questions regarding this feature, feel free to reach out, and our engineers will be happy to help!