Dockerize Your Spring Boot App Like a Pro

Anil Gulati
3 min readSep 8, 2023

--

Docker Logo

When it comes to Dockerizing your Spring Boot application, following best practices is key to ensuring a smooth and efficient deployment. In this article, we’ll delve into these practices and provide code examples to help streamline your Dockerization process.

1. Choose the Right Base Image

Selecting the appropriate base image is crucial for your Spring Boot app. Opt for an OpenJDK base image that aligns with your Java version, ensuring compatibility and efficiency. Here’s a snippet using OpenJDK 11 as an example:

FROM openjdk:11
COPY target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

2. Build a Slim Image

Keep your Docker image size minimal for faster transfers, reduced storage requirements, and quicker container startups. Employ multi-stage builds to achieve this. Check out this example:

# First stage: build the application
FROM maven:3.8.3-jdk-11 AS build
COPY . /app
WORKDIR /app
RUN mvn package -DskipTests

# Second stage: create a slim image
FROM openjdk:11-jre-slim
COPY --from=build /app/target/my-application.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

3. Leverage Environment Variables

Harness environment variables to configure your Spring Boot app dynamically without Docker image rebuilds. This example sets an environment variable for the active profile:

FROM openjdk:11
ENV SPRING_PROFILES_ACTIVE=production
COPY target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

4. Docker Compose for Service Definitions

Use Docker Compose to define your app’s services and dependencies, simplifying management and deployment. This snippet demonstrates defining a Spring Boot app and a MySQL database:

version: '3'
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
MYSQL_DATABASE: my-database
volumes:
- db_data:/var/lib/mysql
web:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/my-database
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: my-secret-pw
volumes:
db_data:

5. Implement a Reverse Proxy

Enhance your app’s scalability, security, and load balancing by employing a reverse proxy to manage incoming traffic. Here’s an example of using Nginx as a reverse proxy in a Docker Compose setup:

version: '3'
services:
web:
build: .
environment:
SPRING_PROFILES_ACTIVE: production
ports:
- "8080:8080"
proxy:
image: nginx
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web

6. Monitor with Health Checks

Ensure the health of your application by implementing health checks, which can help in automatic recovery or scaling based on the application’s status. Add a health check to your Docker image like this:

FROM openjdk:11
COPY target/my-application.jar app.jar
HEALTHCHECK --interval=5s \
--timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "/app.jar"]

7. Optimize with Docker Caching

Speed up image builds by utilizing Docker caching. Multi-stage builds and caching dependencies can significantly reduce build times. Here’s an example:

FROM openjdk:11 as builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline

COPY src/ ./src/
RUN mvn package -DskipTests

FROM openjdk:11
COPY --from=builder /app/target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

8. Use a .dockerignore File

Exclude unnecessary files and directories from the Docker build context using a .dockerignore file. Improve build performance and security with this practice

# Ignore all files in the root directory
*
# Include the src directory
!src/
# Include the pom.xml file
!pom.xml
# Exclude the target directory and its contents
target/

9. Add Metadata with Labels

Enhance Docker image usability and maintainability by adding metadata labels. These labels provide information about the image, such as its version or maintainer. Here’s an example:

FROM openjdk:11
LABEL maintainer="John Doe <john.doe@example.com>"
LABEL version="1.0"
LABEL description="My Spring Boot application"
COPY target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

10. Embrace Container Orchestration

For production environments, employ container orchestration tools like Kubernetes or Docker Swarm. These tools automate deployment, scaling, and management, ensuring high availability and scalability. Here’s a snippet of a Kubernetes deployment file:

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-application
labels:
app: my-application
spec:
replicas: 3
selector:
matchLabels:
app: my-application
template:
metadata:
labels:
app: my-application
spec:
containers:
- name: my-application
image: my-registry/my-application:1.0
ports:
- containerPort: 8080

In conclusion, Dockerizing your Spring Boot application can be a streamlined process when you adhere to these best practices. They empower you to leverage the advantages of Docker and facilitate deployments across various platforms.

Enjoyed This Article?

If you enjoy reading this post, got help, knowledge through it, and want to support my efforts please clap this article and follow.
Originally published on
blog.anilgulati.com
To explore more of my work, visit my portfolio at
anilgulati.com .

--

--

Anil Gulati

Associate Software Engineer @YMSLI | Ex-SDE@Onelab Ventures | Full Stack Developer Visit my portfolio @ https://anilgulati.com