Modern Java Deployment: Docker and Kubernetes
The End of “It Works on My Machine”
Containerization has revolutionized how Java applications are deployed. By packaging the JRE and dependencies into a single image, you ensure identical behavior across development, staging, and production.
Core Concepts
1. Docker
An platform to develop, ship, and run applications inside isolated environments called Containers.
- Dockerfile: The recipe for your image.
- Image: The read-only template.
- Container: The running instance.
2. Kubernetes (K8s)
An orchestration system for managing clusters of containers. It handles scaling, self-healing (restarting failed containers), and load balancing.
Practice Exercise: From Code to Cluster
Step 1: The Dockerfile
We’ll use a multi-stage build to keep the final image small.
# Stage 1: Build
FROM maven:3.9-eclipse-temurin-17 AS build
COPY . .
RUN mvn clean package -DskipTests
# Stage 2: Run
FROM eclipse-temurin:17-jre-alpine
COPY --from=build target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
Step 2: Kubernetes Deployment (YAML)
Define how many replicas you want and how to access them.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-app
spec:
replicas: 3
selector:
matchLabels:
app: spring-app
template:
metadata:
labels:
app: spring-app
spec:
containers:
- name: spring-app
image: myregistry/spring-app:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: spring-service
spec:
selector:
app: spring-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
Why This Works
- Immutability: Once an image is built, it never changes. This eliminates “Configuration Drift” between environments.
- Orchestration: Kubernetes monitors your pods. If one crashes, it instantly spins up a replacement. If traffic spikes, you can scale from 3 to 100 replicas with a single command.
Performance Tip: JVM Container Awareness
Older versions of Java (pre-10) were not aware of container resource limits (CPU/RAM). They would see the total memory of the host machine and potentially crash the container. Always use Java 17+ and alpine-based small images to minimize start-up time and security surface area.
Summary
Mastering Docker and Kubernetes is a required skill for any modern backend developer. By containerizing your Java service, you transform it from a “fragile script” into a “resilient cloud-native component.”