How to minimize Docker image size for Spring Boot Applications
Introduction
Image size matters in the cloud-native application world. No one wants to see a large image size in the image repository. In short, to remember why image size is important;
- Efficient Distribution: Smaller image sizes allow for faster and more efficient distribution of containers across networks.
- Faster Deployment: Smaller images result in faster container startup times.
- Optimized Resource Utilization: Docker images are stored and run on Docker hosts. Smaller image sizes require less disk space, optimising resource utilization on the host machine.
- Security: Smaller images reduce the attack surface and potential vulnerabilities.
- Version Control and Maintenance: Smaller images are easier to manage, update, and version control. When you have smaller images, updating or modifying specific components becomes less complex and time-consuming.
Let's find out how we can reduce the Spring Boot image size.
Jlink
Java jlink
is a command-line tool introduced in Java 9 as a part of the Java 9 modules. It allows you to create a custom runtime image that includes only the necessary modules and dependencies required by your Java application, thereby reducing its size and improving startup time.
Here's why you might need jlink
:
- Reduced application size
- Faster startup time
- Modularization support
- Deployment flexibility
To use jlink
, you need to define a module descriptor (module-info.java) for your application, which specifies the modules your application requires and exposes to other modules. Then, you can use the jlink
command-line tool to create a custom runtime image based on those module dependencies.
Overall, jlink
empowers developers to create optimized, standalone Java applications tailored to their specific requirements, leading to improved performance and a more efficient deployment process.
Docker file with Builder Image
Using a Docker builder image provides several benefits when it comes to building and packaging applications within a Docker environment. Here are some reasons:
- Isolation and reproducibility
- Consistent development and production environments
- Dependency management
- Scalability and portability
- Build optimizations
- Continuous integration and deployment (CI/CD)
Overall, Docker builder images simplify the process of building applications by providing an isolated, reproducible, and consistent environment. They help streamline the development workflow, enhance collaboration, and improve the overall efficiency of building and packaging applications within a Docker ecosystem.
Sample Dockerfile
# Custom Java runtime using jlink in a multi-stage container build
FROM eclipse-temurin:17 as jre-build
# Create a custom Java runtime
RUN $JAVA_HOME/bin/jlink \
--add-modules jdk.unsupported,java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
--strip-debug \
--no-man-pages \
--no-header-files \
--compress=2 \
--output /javaruntime
# Define your base image
FROM debian:stretch-slim
ENV JAVA_HOME=/opt/java/openjdk
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=jre-build /javaruntime $JAVA_HOME
RUN mkdir /opt/app
COPY target/*.jar /opt/app/app.jar
CMD ["java", "-jar", "/opt/app/app.jar"]
If you have a Spring Boot application with a size of about 50 MB, the sample Dockerfile will create a 150 MB image for you.
Conclusion
In this article, I have covered Jlink and Docker builder image configuration for the smallest Spring Boot docker images. I hope it will be helpful.
See you in the next article. 👻