Deploying Spring Boot Applications with Docker

In the era of modern microservices and cloud-native architectures, packaging Java backend applications into images for containerized delivery has become an industry standard. As a framework designed to rapidly build standalone Spring applications, Spring Boot is naturally suited for Docker deployment. Unlike traditional virtual machine or physical server installations that require dependency packages (JAR/WAR), Docker provides a deterministic environment with "build once, run anywhere," effectively solving the classic issue of "it works on my machine" caused by operating system differences.

Before writing your Dockerfile, it is essential to understand the core concepts: an image is a packaged file containing both the application and its runtime environment; a container is an instance running based on that image; and Docker Compose allows us to orchestrate multiple services (such as applications, databases) together for deployment. Ensure you have installed Docker Desktop or Docker CE locally and can execute docker run commands correctly.

Building Spring Boot Applications with Dockerfile

Writing an optimized Dockerfile is key to successful deployment. For Java applications, we typically adopt a multi-stage build strategy to minimize the final image size: first compiling and packaging the project within a full JDK environment, then copying the generated JAR file into a lightweight base image for execution.

Here are the standard steps and example code for writing a Dockerfile:

  1. Select Base Image: It is recommended to use eclipse-temurin:21-jre (OpenJDK 21) or the officially recommended openjdk:21-slim. These images are smaller and more secure compared to traditional Debian-based Java images.
  2. Multi-stage Build Logic:
    • Stage One: Compile and package using a toolchain with a complete JDK installed.
    • Stage Two: Copy the generated JAR file into the lightweight base image.
# Define name and tag (optional)
FROM eclipse-temurin:21-jre AS builder

WORKDIR /app
COPY pom.xml .
RUN mvn clean package -DskipTests

# Switch to a lighter base image to reduce final volume
FROM openjdk:21-slim

WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

Note: When configuring the Maven plugin in pom.xml, ensure you add <skipTests>true</skipTests> to avoid excessive build time caused by test execution. Additionally, it is recommended to remove development dependencies (such as IDE support libraries) for production environments and enable JVM parameters to optimize memory usage.

Orchestrating Multi-Service Environments with Docker Compose

Deploying a single application often fails to meet real-world business requirements; middleware such as databases, caches, and message queues also require containerization. Docker Compose allows us to define configuration files for multiple services (docker-compose.yml), enabling one-click startup of an entire microservices cluster.

Through docker-compose.yml, we can declare dependencies between the Spring Boot application and MySQL/Redis:

version: '3.8'

services:
  app:
    build: .          # Reference Dockerfile in current directory
    ports:
      - "8080:8080"   # Map host port to container internal port
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/myapp?useSSL=false&serverTimezone=UTC
      SPRING_DATA_REDIS_HOSTS: redis:6379
    depends_on:
      - db
      - redis

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root123456
    volumes:
      - ./mysql-data:/var/lib/mysql

  redis:
    image: redis:7-alpine

This configuration enables network interconnectivity between services: the Spring Boot application accesses db and redis containers directly via environment variables without needing additional DNS configuration. During development, debug mode can be enabled (e.g., adding -Dspring.profiles.active=dev). In production environments, switch to the corresponding profile and set up security password policies.

Verifying Deployment Status and Log Monitoring Mechanisms

After construction, it is necessary to verify image correctness through actual execution. Use docker-compose up -d command to start all services in background mode; subsequently, perform health checks via the following workflow:

  1. Check Container Status: Execute docker ps --format "table {{.ID}}\t{{.Names}}" to confirm that all services are running normally and in an Up state.
  2. Access Application Interface: Request http://localhost:8080/actuator/health (if Spring Boot Actuator is configured) via a browser or command line to check if the health result shows UP.
  3. Real-time Log Monitoring: Use docker-compose logs -f app to track container output, quickly locating issues such as startup failures, port conflicts, or dependency exceptions.

Furthermore, it is recommended to integrate monitoring systems like Prometheus + Grafana, exposing application metrics to Docker Exporter for visual performance analysis and alert notifications. For high availability scenarios, you can also configure multi-replica deployment strategies and auto-scaling rules (Kubernetes) to further enhance system elasticity and stability.