Home NewsX Java,Spring,Spring boot,Azure Container Apps

Java,Spring,Spring boot,Azure Container Apps

by info.odysseyx@gmail.com
0 comment 15 views


introduction

In the cloud-native era, the need for rapid application launch and automated scaling has become more important. This is especially true for Java applications that require enhanced solutions to effectively meet these requirements. In a previous blog post Accelerate Java applications on Azure Kubernetes Service using CRaCWe explored ways to address these issues using CRaC technology. CRaC promotes efficient scaling operations by speeding up application startup and reducing recovery times. In this blog post, we’ll take a closer look at how to optimize container images in particular. Azure container apps (ACA) Multi-step build, spring boot layer toolsand Class Data Sharing (CDS) Create highly optimized Docker images. Combining these techniques improves both the image footprint and startup performance of Java applications on ACA. These improvements make Java applications more agile and responsive for frequent cloud-native deployments, helping them meet modern operational requirements.

Key Takeaways

After testing various Docker optimization techniques, we observed the following improvements in Azure Container Apps:

  • A multi-stage build reduces image size by 33%, allowing you to import images faster.
  • Spring Boot Layer Tools further optimize the build process by reducing unnecessary rebuilds and slightly improve image fetch and startup times.
  • Class Data Sharing (CDS) provided the strongest benefit, reducing application startup time by 27% and significantly improving runtime performance.

These optimizations not only reduce the size and import time of images, but also make deployment more efficient, saving both time and resources.

Optimization technology overview

Multi-step build

Multi-stage builds are a powerful Docker feature that allows you to create more compact images by reducing the layers required for the final build. The first step allows you to do all the heavy lifting, including compiling code and downloading dependencies. In the final step, only the required artifacts are copied, excluding any dependencies, at build time.

Leveraging multi-stage builds significantly reduces overall image size, resulting in faster pooling times and more efficient use of resources.

spring boot layer tools

The Spring Boot tiering tool further optimizes the tiering process for Docker images by logically partitioning your application into tiers. Each layer consists of different components of a Spring Boot application, including dependencies, the Spring Boot framework, and the application code itself. This reduces build times and improves performance when pushing updates because Docker rebuilds and caches only the layers that have changed.

This also improves startup times, as unchanged layers can be loaded from cache more quickly.

Class Data Sharing (CDS)

CDS is a Java feature that allows class metadata to be shared between different Java processes. Application Class Data Sharing (AppCDS) allows you to further optimize startup times by archiving your application classes during the build process. This reduces class loading overhead at runtime, improving startup speed by avoiding redundant class loading operations.

When integrated with Docker, CDS can be used to store shared class metadata that is reused when container restarts, significantly improving startup performance.

Technology application: step-by-step optimization

Now let’s look at how these techniques can be applied incrementally to optimize Docker images and improve startup times. The blog uses a repository. Spring Pet Clinic

Step 0: Starting point: Base Docker image

Before we look at optimizations, let’s look at a typical Dockerfile that can be used without optimizations. This base Docker image contains only the essential elements needed to run a Spring Boot application.

FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu

WORKDIR /home/app
ADD . /home/app/spring-petclinic-main
RUN cd spring-petclinic-main && ./mvnw -Dmaven.test.skip=true clean package && cp ./target/*.jar /home/app/petclinic.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "petclinic.jar"]

This Dockerfile simply builds and copies the packaged JAR file and runs it using the default java -jar command. Although functional, it lacks optimization for image size and startup speed. The entire application along with all dependencies is bundled in a single layer. This means that any changes to your application require a rebuild of the entire image. Additionally, no optimizations are applied at runtime to reduce class loading overhead. The startup time reflects the JVM’s default class loading behavior.

Basic image metrics for comparison

optimization step Image size (MB) Image retrieval time (seconds) Start time (seconds)
Base image (no optimization) 734 8.017 7,649

Additionally, base Docker images often need to include various build tools (e.g. Maven, JDK) to successfully compile your code. This not only increases the image size, but also creates more potential vulnerabilities due to: Including additional packages makes you more vulnerable to Common Vulnerability and Exposures (CVE).

Step 1: Use a multi-stage build

Multi-stage builds help reduce image size by separating the build environment from the runtime environment. A multi-stage Dockerfile first compiles the application in a build phase, then copies only the necessary runtime artifacts into a much thinner runtime phase.

# Stage 1: Build Stage
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS builder

WORKDIR /home/app
ADD . /home/app/spring-petclinic-main
RUN cd spring-petclinic-main && ./mvnw -Dmaven.test.skip=true clean package

# Stage 2: Final Stage
FROM mcr.microsoft.com/openjdk/jdk:17-mariner

WORKDIR /home/app
EXPOSE 8080
COPY --from=builder /home/app/spring-petclinic-main/target/*.jar petclinic.jar
ENTRYPOINT ["java", "-jar", "petclinic.jar"]

Multi-stage build metrics

optimization step Image size (MB) Image retrieval time (seconds) Start time (seconds)
Base image (no optimization) 734 8.017 7,649
Multi-level construction 492 7.145 7.932

With a multi-stage build, the resulting image contains only the compiled application and its dependencies, excluding heavy build tools such as Maven. Using a multi-stage build reduces image size by 33% and slightly improves image fetch times, while keeping startup times close to the base image.

Step 2: Optimization using Spring Boot Layer tools

Next, we add Spring Boot layer tools to optimize the structure of our application layer.

# Stage 1: Build Stage
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS builder

WORKDIR /home/app
ADD . /home/app/spring-petclinic-main
RUN cd spring-petclinic-main && ./mvnw -Dmaven.test.skip=true clean package

# Stage 2: Layer Tool Stage
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS optimizer

WORKDIR /home/app
COPY --from=builder /home/app/spring-petclinic-main/target/*.jar petclinic.jar
RUN java -Djarmode=layertools -jar petclinic.jar extract

# Stage 3: Final Stage
FROM mcr.microsoft.com/openjdk/jdk:17-mariner

ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
COPY --from=optimizer /home/app/dependencies/ ./
COPY --from=optimizer /home/app/spring-boot-loader/ ./
COPY --from=optimizer /home/app/snapshot-dependencies/ ./
COPY --from=optimizer /home/app/application/ ./

layer tool metrics

Optimization step Image size (MB) Image retrieval time (seconds) Start time (seconds)
Base image (no optimization) 734 8.017 7,649
Multi-level construction 492 6.987 7.932
spring boot layer tools 493 7.104 7.805

Typically, the Spring framework itself and its dependencies are much larger than application-specific classes. The Layers tool allows you to place these large, rarely changing components (such as the Spring framework and external libraries) in lower layers of your image, while application-specific code resides in the top layer. Constructing images in this way not only optimizes build times, but also reduces bandwidth usage when transferring images. This ensures that only changed layers are updated, improving build efficiency and faster startup for subsequent updates.

Step 3: Class Data Sharing (CDS) Integration

Finally, we integrate CDS for class loading optimization.

# Stage 1: Build Stage
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS builder

WORKDIR /home/app
ADD . /home/app/spring-petclinic-main
RUN cd spring-petclinic-main && ./mvnw -Dmaven.test.skip=true clean package

# Stage 2: Layer Tool Stage
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS optimizer

WORKDIR /app
COPY --from=builder /home/app/spring-petclinic-main/target/*.jar petclinic.jar
RUN java -Djarmode=tools -jar petclinic.jar extract --layers --launcher


# Stage 3: Optimize with CDS Stage
FROM mcr.microsoft.com/openjdk/jdk:17-mariner

COPY --from=optimizer /app/petclinic/dependencies/ ./
COPY --from=optimizer /app/petclinic/spring-boot-loader/ ./
COPY --from=optimizer /app/petclinic/snapshot-dependencies/ ./
COPY --from=optimizer /app/petclinic/application/ ./
RUN java -XX:ArchiveClassesAtExit=./application.jsa -Dspring.context.exit=onRefresh org.springframework.boot.loader.launch.JarLauncher
ENTRYPOINT ["java", "-XX:SharedArchiveFile=application.jsa", "org.springframework.boot.loader.launch.JarLauncher"]

This setting significantly reduces class loading time, making application startup faster.

Optimization through Class Data Sharing (CDS)

Optimization step Image size (MB) Image retrieval time (seconds) Start time (seconds)
Base image (no optimization) 734 8.017 7,649
Multi-level construction 492 6.987 7.932
spring boot layer tools 493 7.104 7.805
CDS 560 7.145 5.562

conclusion

By integrating multi-stage builds, Spring Boot Layer tooling, and class data sharing into your Docker images, you can optimize both the size and performance of your Java applications in Azure Container Apps. Each technique addresses a different aspect of optimization, including reducing image bloat, improving layer caching, and improving class loading efficiency. Together they create a powerful solution for building and deploying highly optimized Java applications in Docker containers.

ACA is an ideal managed platform for running Java applications, providing features tailored to Java workloads, including built-in JVM metrics, diagnostics, and middleware support. These features enable Java applications to perform optimally while simplifying management and scaling in cloud-native environments. For more information, please visit: Azure container app Java overview.





Source link

You may also like

Leave a Comment

Our Company

Welcome to OdysseyX, your one-stop destination for the latest news and opportunities across various domains.

Newsletter

Subscribe my Newsletter for new blog posts, tips & new photos. Let's stay updated!

Laest News

@2024 – All Right Reserved. Designed and Developed by OdysseyX