Dockerized Spring Boot with Multi-Environment Configs

minuth

Minuth Prom

Posted on July 3, 2024

Dockerized Spring Boot with Multi-Environment Configs

Dockerizing a Spring Boot application for multiple environments involves creating Docker images that can be configured differently based on the deployment environment (development, testing, production, etc.). This ensures that the application behaves consistently across various development and deployment stages.

We will use Docker Multi-Stage and Spring Boot Externalized Configuration in this configuration.

Using Docker Multi-Stage builds allows for creating smaller, more efficient Docker images by separating the build process into multiple stages. This reduces the final image size. More detail about Multi-stage builds | Docker Docs.

Spring Boot Externalized Configuration, on the other hand, enables the application to be easily reconfigured for different environments without changing the code. This is achieved by externalizing environment-specific configurations, making the application more flexible and easier to manage across development, testing, and production environments. More detail about Externalized Configuration :: Spring Boot

Gradle Project

Dockerfile

# Stage 1: Build the application
FROM gradle:8.8-jdk17 AS build

# Set the working directory in the container
WORKDIR /app

# Copy the Gradle build files
COPY build.gradle settings.gradle ./

# Copy the source code
COPY src ./src

# Build the application
RUN gradle build --no-daemon

# Stage 2: Create the runtime image
FROM openjdk:17-jdk-slim

# Set the working directory in the container
WORKDIR /app

# Copy the built JAR file from the Gradle build stage
COPY --from=build /app/build/libs/*.jar app.jar

# Expose the port the application runs on
EXPOSE 8080

# Command to run the application
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.config.location=optional:classpath:/,optional:file:config/"]

Enter fullscreen mode Exit fullscreen mode

.dockerignore

# Ignore build directory where Gradle output files are stored
build/

# Ignore Gradle wrapper files
gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties

# Ignore IntelliJ IDEA project files
*.iml
.idea/

# Ignore Eclipse project files
.project
.classpath
.settings/

# Ignore NetBeans project files
nbproject/

# Ignore Mac OS X folder attributes
.DS_Store

# Ignore Linux trash files
.Trash-*

# Ignore node_modules if there's any front-end part
node_modules/

# Ignore log files
*.log

# Ignore temporary files
*.tmp
*.swp
*.swo

# Ignore backup and old files
*.bak
*.old

# Ignore environment files (optional, if you use them)
.env
.env.local

Enter fullscreen mode Exit fullscreen mode

Maven Project

Dockerfile

# Stage 1: Build the application
FROM maven:3.8.4-openjdk-17 AS build

# Set the working directory in the container
WORKDIR /app

# Copy the pom.xml and download dependencies
COPY pom.xml ./
RUN mvn dependency:go-offline -B

# Copy the source code and build the application
COPY src ./src
RUN mvn package -DskipTests

# Stage 2: Create the runtime image
FROM openjdk:17-jdk-slim

# Set the working directory in the container
WORKDIR /app

# Copy the jar file from the build stage
COPY --from=build /app/target/*.jar app.jar

# Expose the port the application runs on
EXPOSE 8080

# Command to run the application
ENTRYPOINT ["java", "-jar", "app.jar", "--spring.config.location=optional:classpath:/,optional:file:config/"]

Enter fullscreen mode Exit fullscreen mode

.dockerignore

# Ignore target directory where Maven output files are stored
target/

# Ignore Maven local repository (optional)
.m2/

# Ignore IntelliJ IDEA project files
*.iml
.idea/

# Ignore Eclipse project files
.project
.classpath
.settings/

# Ignore NetBeans project files
nbproject/

# Ignore Mac OS X folder attributes
.DS_Store

# Ignore Linux trash files
.Trash-*

# Ignore node_modules if there's any front-end part
node_modules/

# Ignore log files
*.log

# Ignore temporary files
*.tmp
*.swp
*.swo

# Ignore build output
build/

# Ignore other files that are not needed in the image
*.bak
*.old

# Ignore environment files (optional, if you use them)
.env
.env.local

Enter fullscreen mode Exit fullscreen mode

The --spring.config.location=optional:classpath:/,optional:file:config/ parameter is used to specify the locations from which Spring Boot should load its configuration files. Here's a breakdown of what it does:

  • optional:classpath:/: This tells Spring Boot to look for configuration files on the classpath (typically inside the JAR file). The optional: prefix means that Spring Boot will not fail if the configuration file is not found in this location.
  • optional:file:config/: This tells Spring Boot to look for configuration files in the config/ directory on the file system in the container.

By using this parameter, you can externalize your configuration files, making it easier to manage different configurations for different environments (development, testing, production) without changing the application code. This is particularly useful when you want to override default configurations with environment-specific settings.

In the context of the provided Dockerfile, this parameter allows the Docker container to use configuration files from the config/ directory, which is mapped to a volume on the host machine. This way, you can easily update configuration settings without rebuilding the Docker image.

Build and run without Docker Compose file

  • Build: docker build -t springboot-dockerize .
  • Run: docker run -p 8081:8080 -v D:/configuration/demo-spring-boot-dockerize/:/app/config/ springboot-dockerize
    • -p 8081:8080: This flag maps port 8081 on the host machine to port 8080 on the container. It allows you to access the application running inside the container via port 8081 on the host.
    • -v D:/configuration/demo-spring-boot-dockerize/:/app/config/: This flag mounts the directory D:/configuration/demo-spring-boot-dockerize/ from the host machine to the /app/config/ directory inside the container. This is used to provide external configuration.

Using Docker Compose file

version: '3.8'

services:
  springboot-app:
    image: springboot-dockerize
    ports:
      - "${HOST_PORT}:8080"
    volumes:
      - "${CONFIG_PATH}:/app/config/"

Enter fullscreen mode Exit fullscreen mode

Using environment variables HOST_PORT and CONFIG_PATH allows for flexibility and reusability of the Docker Compose configuration.

  • Run with system environment variables or .env file: docker compose up --build

    Make sure to set the environment variables HOST_PORT and CONFIG_PATH in your system or in a .env file in the same directory as your docker-compose.yml:

    HOST_PORT=8081
    CONFIG_PATH=D:/configuration/demo-spring-boot-dockerize/
    
  • Run with inline environment variable: HOST_PORT=8081 CONFIG_PATH=D:/configuration/demo-spring-boot-dockerize/ docker compose up --build

💖 💪 🙅 🚩
minuth
Minuth Prom

Posted on July 3, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related