Dockerizing a Java App the Right Way in 2026
Multi-stage builds, layered JARs, distroless images, and the JVM flags that make containers behave. A production Dockerfile you can actually copy.

A naive FROM openjdk Dockerfile produces a 600MB image that rebuilds from
scratch on every code change and ignores the container’s memory limits. Let’s
fix all three problems.
Use multi-stage builds
Build with a full JDK, run with a slim JRE. The build tools never ship to production.
# ---- build stage ----
FROM eclipse-temurin:21-jdk AS build
WORKDIR /app
COPY . .
RUN ./mvnw -q -DskipTests package
# ---- runtime stage ----
FROM eclipse-temurin:21-jre AS runtime
WORKDIR /app
COPY --from=build /app/target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Layer your JAR for fast rebuilds
Spring Boot can split a JAR into layers (dependencies change rarely, your code
changes constantly). Ordering COPY from least- to most-volatile means Docker
reuses cached layers:
FROM eclipse-temurin:21-jre AS runtime
WORKDIR /app
COPY --from=build /app/target/dependencies/ ./
COPY --from=build /app/target/spring-boot-loader/ ./
COPY --from=build /app/target/snapshot-dependencies/ ./
COPY --from=build /app/target/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
Respect container memory limits
Modern JVMs are container-aware, but be explicit. Set a percentage of the
container’s memory rather than a fixed -Xmx:
ENV JAVA_OPTS="-XX:MaxRAMPercentage=75 -XX:+UseG1GC"
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
Without
MaxRAMPercentage, a JVM in a 512MB container can still try to grab a heap sized for the host machine — and get OOM-killed.
Go distroless for the smallest, safest image
Distroless images contain only your app and the JRE — no shell, no package manager, a tiny attack surface:
FROM gcr.io/distroless/java21-debian12
COPY --from=build /app/target/app.jar /app.jar
ENTRYPOINT ["/app.jar"]
The checklist
- ✅ Multi-stage build (JDK to build, JRE/distroless to run)
- ✅ Layered copy for cache-friendly rebuilds
- ✅
MaxRAMPercentageinstead of fixed heap - ✅ Non-root user (distroless runs as nonroot by default)
- ✅ A real
.dockerignore(don’t shiptarget/,.git,node_modules)
Do these five things and your image drops from ~600MB to ~180MB, rebuilds in seconds, and behaves predictably under a memory limit.
Related articles

Building a Full SaaS Application with NestJS, React, PostgreSQL and Docker
A step-by-step, production-grade guide: architecture, multi-tenant database design, JWT auth, NestJS APIs, a React frontend, Docker, CI/CD with GitHub Actions, scalability, and the best practices that hold up in production.

Even Realities Hits $1B Betting Against the Camera in Smart Glasses
Even Realities, a Shenzhen startup founded by ex-Apple engineers, raised $150M in a pre-Series B led by Meituan and Tencent on July 6, 2026, reaching a $1 billion valuation. Its pitch: camera-free, display-first smart glasses that take on Meta on privacy. Here's the round, the product, and the strategy.

Microsoft Cuts 4,800 Jobs and Guts Xbox in a 'Painful Reset' for AI
Microsoft is cutting roughly 4,800 jobs (about 2.1% of its workforce) on July 6, 2026, with Xbox facing up to 3,200 cuts over the next year and four studios — Ninja Theory, Undead Labs, Compulsion Games and Double Fine — divested. Here's what happened, who's affected, and why it's framed as an AI-spending reset.
Have a project or an idea?
We don't just write about software — we build it. Tell us what you're working on and we'll get back within 1–2 business days.