Two main files
Dockerfile
- How to build an image (turn code → image)
- what base environment to start from (e.g., Python)
- what files to copy into the image (your code)
- what dependencies to install (pip install)
- what command to run when the container starts (
uvicorn)
docker-compose.yml
- How to run multiple containers together, including
- which services to run (redis, api, db, etc.)
- which image to use (
image: redis:7) or how to build it (build: .)
- ports mapping (host ↔ container)
- environment variables
- volumes for persistent data
- dependencies and startup order
- shared network (so services can talk using service names like
redis)
Dockerfile
Typical structure for Spring boot
- Builder stage (Maven + JDK)
- copy
pom.xml first
- download dependencies (cached if
pom.xml unchanged)
- copy
src/ and build JAR (mvn package)
- Runtime stage (lightweight JDK/JRE)
- copy only the built JAR from builder
- run
java -jar app.jar
- optionally run as non-root user
Example: Dockerfile
- use a multi-stage Dockerfile:
- the first stage builds the Spring Boot app with Maven into a JAR (with dependency caching)
- the second stage runs that JAR on a lightweight JDK image for a smaller and more secure container.
# Stage 1: Build stage using Maven
FROM maven:3.9-eclipse-temurin-17 AS builder
# Set working directory
WORKDIR /app
# Copy Maven configuration
# This allows Docker to cache dependencies separately
COPY pom.xml .
# Download dependencies (cached if pom.xml hasn't changed)
RUN mvn dependency:go-offline
# Copy source code
COPY src ./src
# Build the application
RUN mvn clean package -DskipTests
# Stage 2: Runtime stage using lightweight JDK
FROM openjdk:17.0.1-jdk-slim
# Create non-root user for security
RUN groupadd -g 1000 spring && useradd -u 1000 -g spring -s /bin/sh -M spring
# Set working directory
WORKDIR /app
# Copy JAR from builder stage
COPY --from=builder /app/target/*.jar app.jar
# Change ownership to non-root user
RUN chown -R spring:spring /app
# JVM memory settings for containers
ENV JAVA_OPTS="-Xmx512m -Xms256m"
# Run the application
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]
docker-compose.yml
Example docker-compose.yml
version: '3.8'
services:
hello-service:
# Build from current directory
build:
context: .
dockerfile: Dockerfile
# Container name for easier identification
container_name: hello-service-container
# Port mapping: host:container
ports:
- "8080:8080"
# Environment variables
environment:
- SPRING_PROFILES_ACTIVE=docker
- JAVA_OPTS=-Xmx256m -Xms128m
# Health check
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/api/hello"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Restart policy
restart: unless-stopped
# Resource limits
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M