Optimising Spring Boot Docker Images: A Guide to Lean, Secure, and Efficient Containers
Created using AI: gencraftcom

Optimising Spring Boot Docker Images: A Guide to Lean, Secure, and Efficient Containers

If you’re deploying Spring Boot apps in Docker containers, you’ve probably faced the dreaded 1GB+ image size, slow CI/CD pipelines, or even worse – security vulnerabilities in production.

But here’s the good news: with a few best practices, you can shrink your images, speed up deployments, and lock down your containers. Let’s dive in.


Why Optimise Your Docker Images?

- Smaller Images: Faster deployments, lower cloud storage costs.

- Faster Builds: Improved developer productivity.

- Enhanced Security: Fewer vulnerabilities and reduced attack surface.

(Fun fact: A well-optimised Spring Boot image can be under 200MB!)


The Optimisation Checklist

1. Use Multi-Stage Builds

Multi-stage builds allow you to separate the build environment from the runtime environment, ensuring only the necessary artifacts make it into the final image.

# Build stage  
FROM maven:3.9.6-eclipse-temurin-21 AS builder  
WORKDIR /app  
COPY . .  
RUN mvn clean package  

# Runtime stage  
FROM eclipse-temurin:21-jre-jammy  
WORKDIR /app  
COPY --from=builder /app/target/*.jar app.jar  
ENTRYPOINT ["java", "-jar", "app.jar"]          

Key Benefit: Removes build tools and dependencies, reducing image size by 300MB+.


2. Leverage Spring Boot Layer Tools

Spring Boot 2.3+ introduced layer tools, which split your JAR into logical layers:

- Dependencies (rarely change)

- Snapshot dependencies (change occasionally)

- Application code (changes frequently)

This allows Docker to cache layers independently, speeding up rebuilds.

Enable in pom.xml:

<configuration>  
  <layers>  
    <enabled>true</enabled>  
  </layers>  
</configuration>          

Result: Up to 70% faster rebuilds when only application code changes.


3. Choose the Right Base Image

The base image you choose has a huge impact on size and security. Here’s a quick comparison:

| Base Image | Size | Use Case |

|------------------|--------|---------------------------|

| eclipse-temurin | 150MB | General-purpose |

| distroless | 75MB | Security-critical apps |

| Alpine Linux | 100MB | Avoid if using JNI/native |

Pro Tip: Use distroless for production – it’s minimal and secure.


4. Run as a Non-Root User

Running containers as root is a major security risk. Always create and switch to a non-root user:

RUN addgroup --system spring && adduser --system --ingroup spring spring  
USER spring:spring          

5. Optimise JVM Memory Settings

Configure the JVM to respect container memory limits:

ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75%"         

This ensures your app plays nicely with Kubernetes and avoids out-of-memory crashes.


Tools to Supercharge Your Workflow

- `dive`: Analyse image layers and identify bloat.

- `trivy`: Scan images for vulnerabilities.

- `spring-boot-build-image`: Automate optimisations with Paketo Buildpacks.


Real-World Impact

A recent project saw:

- 📉 **85% smaller images** (1.2GB → 180MB)

- ⚡ **65% faster CI/CD pipelines**

- 🔐 **0 critical CVEs** in production images


Your Action Plan

1. Audit your current images with docker scout.

2. Implement multi-stage builds.

3. Switch to a slim base image like distroless.

4. Add non-root users and JVM memory tweaks.



Rahul Saini

IT | Java | Python | Cloud | Data Science [ML - AI]

6mo

further, add, 6) Optimize Dockerfile Layers, compact the layers using && 7) Docker Caching 8) SpringBoot Native Images (GraalVM)

Very helpful

Like
Reply

To view or add a comment, sign in

More articles by Rohit Jain

Others also viewed

Explore content categories