Deploying Spring Boot Applications

A comprehensive guide to deploying Spring Boot applications to various cloud platforms and containers

Deploying Spring Boot Applications

This guide covers different deployment strategies for Spring Boot applications, including containerization, cloud platforms, and best practices.

Video Tutorial

Learn more about Spring Boot deployment in this comprehensive video tutorial:

Prerequisites

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

Docker Containerization

Dockerfile

# Build stage
FROM maven:3.8.4-openjdk-17-slim AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

# Run stage
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Docker Compose

version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/myapp
    depends_on:
      - db
  
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword

Kubernetes Deployment

Deployment YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-boot-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: spring-boot-app
  template:
    metadata:
      labels:
        app: spring-boot-app
    spec:
      containers:
        - name: spring-boot-app
          image: your-registry/spring-boot-app:latest
          ports:
            - containerPort: 8080
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: prod
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 8080
          readinessProbe:
            httpGet:
              path: /actuator/health
              port: 8080

Service YAML

apiVersion: v1
kind: Service
metadata:
  name: spring-boot-app
spec:
  selector:
    app: spring-boot-app
  ports:
    - port: 80
      targetPort: 8080
  type: LoadBalancer

AWS Deployment

Elastic Beanstalk

# .elasticbeanstalk/config.yml
branch-defaults:
  main:
    environment: myapp-prod
    group_suffix: null

global:
  application_name: myapp
  branch: null
  default_ec2_keyname: null
  default_platform: Java 17
  default_region: us-west-2
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  repository: null
  sc: git
  workspace_type: Application

ECS Task Definition

{
  "family": "spring-boot-app",
  "containerDefinitions": [
    {
      "name": "spring-boot-app",
      "image": "your-ecr-repo/spring-boot-app:latest",
      "cpu": 1024,
      "memory": 2048,
      "portMappings": [
        {
          "containerPort": 8080,
          "hostPort": 8080,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "SPRING_PROFILES_ACTIVE",
          "value": "prod"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/spring-boot-app",
          "awslogs-region": "us-west-2",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

Google Cloud Platform

Cloud Run

# cloudbuild.yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/spring-boot-app', '.']
  
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/spring-boot-app']
  
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'spring-boot-app'
      - '--image'
      - 'gcr.io/$PROJECT_ID/spring-boot-app'
      - '--platform'
      - 'managed'
      - '--region'
      - 'us-central1'
      - '--allow-unauthenticated'

images:
  - 'gcr.io/$PROJECT_ID/spring-boot-app'

Azure Deployment

Azure Spring Apps

# azure-spring-apps.yml
name: Deploy to Azure Spring Apps

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 17
      uses: actions/setup-java@v2
      with:
        java-version: '17'
        distribution: 'adopt'
        
    - name: Build with Maven
      run: mvn clean package -DskipTests
        
    - name: Login to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}
        
    - name: Deploy to Azure Spring Apps
      uses: azure/spring-apps-deploy@v1
      with:
        azure-subscription: ${{ secrets.AZURE_SUBSCRIPTION }}
        action: Deploy
        service-name: my-spring-app
        app-name: spring-boot-app
        package: target/*.jar

Production Configuration

Application Properties

# application-prod.yml
spring:
  datasource:
    url: ${SPRING_DATASOURCE_URL}
    username: ${SPRING_DATASOURCE_USERNAME}
    password: ${SPRING_DATASOURCE_PASSWORD}
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
  
  jpa:
    hibernate:
      ddl-auto: validate
    properties:
      hibernate:
        jdbc:
          batch_size: 50
  
server:
  port: 8080
  tomcat:
    threads:
      max: 200
    max-connections: 10000
    accept-count: 100
  
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus
  endpoint:
    health:
      show-details: when_authorized
      probes:
        enabled: true

Best Practices

  1. Container Best Practices

    • Use multi-stage builds
    • Optimize layer caching
    • Implement health checks
    • Use non-root users
    • Keep images small
  2. Cloud Platform Best Practices

    • Use managed services
    • Implement auto-scaling
    • Configure monitoring
    • Use secrets management
    • Enable logging
  3. Security Best Practices

    • Use HTTPS
    • Implement rate limiting
    • Configure CORS
    • Use secure headers
    • Enable audit logging
  4. Performance Optimization

    • Configure JVM settings
    • Optimize connection pools
    • Enable caching
    • Use async processing
    • Configure thread pools

Monitoring and Logging

Prometheus Configuration

management:
  endpoints:
    web:
      exposure:
        include: prometheus
  metrics:
    tags:
      application: ${spring.application.name}
    export:
      prometheus:
        enabled: true

ELK Stack Configuration

# logback-spring.xml
<configuration>
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>logstash:5000</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    
    <root level="INFO">
        <appender-ref ref="LOGSTASH"/>
    </root>
</configuration>

CI/CD Pipeline

GitHub Actions

name: CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 17
      uses: actions/setup-java@v2
      with:
        java-version: '17'
        distribution: 'adopt'
        
    - name: Build and Test
      run: mvn clean verify
        
    - name: Build Docker image
      run: docker build -t myapp .
        
    - name: Push to Registry
      run: |
        docker tag myapp registry.example.com/myapp
        docker push registry.example.com/myapp
        
    - name: Deploy to Production
      if: github.ref == 'refs/heads/main'
      run: |
        # Deploy commands here

Conclusion

Successful Spring Boot deployment requires:

  • Proper containerization
  • Cloud platform configuration
  • Production-ready settings
  • Monitoring and logging
  • CI/CD pipeline setup

For more Spring Boot topics, check out: