Dockerizing & Deploying Spring Boot
The final step is getting your Spring Boot application into production. This lesson covers building optimized Docker images with layered JARs, deploying with Docker Compose, and publishing to cloud platforms.
1 Layered JAR Dockerfile
Dockerfile — Optimized Multi-Stage Build
# Stage 1: Extract layers from the Spring Boot fat JAR
FROM eclipse-temurin:21-jre-alpine AS builder
WORKDIR /app
COPY target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
# Stage 2: Final minimal image
FROM eclipse-temurin:21-jre-alpine
# Security: run as non-root
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
WORKDIR /app
# Copy layers in order of least-to-most frequently changing
# (maximizes Docker cache reuse)
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
2 Docker Compose
YAML — docker-compose.yml
version: "3.9"
services:
api:
build: .
ports: ["8080:8080"]
environment:
SPRING_PROFILES_ACTIVE: prod
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/mydb
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
APP_SECURITY_JWT_SECRET: ${JWT_SECRET}
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: mydb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pg_data:
3 Build & Run Commands
Shell — Build & Deploy
# Build JAR
mvn clean package -DskipTests
# Build Docker image
docker build -t my-api:1.0.0 .
# Run with Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f api
# Spring Boot Buildpacks (no Dockerfile needed!)
mvn spring-boot:build-image -Dspring-boot.build-image.imageName=my-api:1.0.0
4 Code Challenge
Challenge: Dockerize your Spring Boot application with the layered JAR Dockerfile. Write a
docker-compose.yml with the API, PostgreSQL, and a Redis container. Deploy to Railway.app using their GitHub integration and verify the /actuator/health endpoint returns UP.