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
-
Container Best Practices
- Use multi-stage builds
- Optimize layer caching
- Implement health checks
- Use non-root users
- Keep images small
-
Cloud Platform Best Practices
- Use managed services
- Implement auto-scaling
- Configure monitoring
- Use secrets management
- Enable logging
-
Security Best Practices
- Use HTTPS
- Implement rate limiting
- Configure CORS
- Use secure headers
- Enable audit logging
-
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: