Spring Boot Deployment
Introduction
Deployment is the process of making your Spring Boot application available to users in a production environment. While development focuses on writing code and testing, deployment ensures that your application is properly installed, configured, and running in an environment where users can access it.
Spring Boot simplifies the deployment process significantly compared to traditional Java applications, offering various deployment options that fit different requirements and infrastructures. In this guide, we'll explore the key deployment strategies for Spring Boot applications and provide step-by-step instructions for each approach.
Understanding Deployment Options
Before diving into specific deployment methods, it's important to understand the main options available:
- JAR Deployment - Spring Boot's embedded server approach
- WAR Deployment - Traditional servlet container approach
- Containerization - Using Docker and similar technologies
- Cloud Platform Deployment - Using AWS, Azure, Google Cloud, etc.
- PaaS Deployment - Platform as a Service options like Heroku
Let's explore each of these options in detail.
JAR Deployment (Standalone Application)
Spring Boot's most common deployment model is as a standalone JAR file with an embedded server. This approach simplifies deployment as you don't need to install a separate application server.
Building a JAR File
To build a JAR file, use Maven or Gradle:
With Maven:
mvn clean package
With Gradle:
./gradlew clean build
These commands create a JAR file in the target
(Maven) or build/libs
(Gradle) directory.
Running the JAR File
To run the JAR file, use the java -jar
command:
java -jar target/myapp-0.0.1-SNAPSHOT.jar
You can also specify configuration properties:
java -jar target/myapp-0.0.1-SNAPSHOT.jar --server.port=8081 --spring.profiles.active=prod
Creating a System Service
For production environments, you'll want your application to run automatically on system startup. Here's how to create a systemd service on Linux:
- Create a service file:
sudo nano /etc/systemd/system/myapp.service
- Add the following content:
[Unit]
Description=My Spring Boot Application
After=syslog.target
[Service]
User=myappuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/java -jar myapp.jar
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
- Enable and start the service:
sudo systemctl enable myapp.service
sudo systemctl start myapp.service
WAR Deployment (Traditional Application Servers)
While JAR deployment is convenient, some organizations still use traditional application servers like Tomcat, JBoss, or WebSphere. Spring Boot supports WAR deployment for these scenarios.
Configuring for WAR Deployment
- Update your
pom.xml
(Maven):
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
- Extend
SpringBootServletInitializer
:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
- Build the WAR file:
mvn clean package
- Deploy the WAR file to your application server:
- For Tomcat: Copy the WAR file to the
webapps
directory - For JBoss/WildFly: Copy to the
deployments
directory - For other servers: Follow their specific deployment process
- For Tomcat: Copy the WAR file to the
Containerization with Docker
Containerization has become extremely popular for deploying applications. Docker allows you to package your application with all its dependencies into a standardized unit.
Creating a Dockerfile
Create a file named Dockerfile
in your project root:
FROM openjdk:17-jdk-slim
VOLUME /tmp
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Building and Running a Docker Image
- Build the Docker image:
docker build -t myapp:latest .
- Run the Docker container:
docker run -p 8080:8080 myapp:latest
Using Docker Compose
For applications with multiple services (e.g., database, cache), you can use Docker Compose:
Create a docker-compose.yml
file:
version: '3'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=secret
depends_on:
- db
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=mydb
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
Run with Docker Compose:
docker-compose up
Cloud Platform Deployment
Modern applications are often deployed to cloud platforms, providing scalability and reliability.
AWS Elastic Beanstalk
- Package your application as a JAR file
- Create an Elastic Beanstalk application through AWS Console or CLI
- Upload your JAR file
- Elastic Beanstalk automatically provisions resources and deploys your application
Example using the AWS CLI:
aws elasticbeanstalk create-application --application-name myapp
aws elasticbeanstalk create-environment --application-name myapp --environment-name myapp-prod --solution-stack-name "64bit Amazon Linux 2 v3.2.8 running Corretto 17"
aws elasticbeanstalk create-application-version --application-name myapp --version-label v1 --source-bundle S3Bucket="mybucket",S3Key="myapp.jar"
aws elasticbeanstalk update-environment --environment-name myapp-prod --version-label v1
Google Cloud Platform (GCP)
To deploy to Google App Engine:
- Create an
app.yaml
file:
runtime: java17
instance_class: F2
- Deploy using the Google Cloud SDK:
gcloud app deploy
Microsoft Azure
To deploy to Azure App Service:
- Install the Azure CLI
- Log in and create a resource group:
az login
az group create --name myResourceGroup --location eastus
- Create an App Service plan:
az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku FREE
- Create a web app:
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name mywebapp --runtime "JAVA:17-java17"
- Deploy your JAR file:
az webapp deploy --resource-group myResourceGroup --name mywebapp --src-path target/myapp.jar --type jar
Platform as a Service (PaaS) Deployment
PaaS options like Heroku simplify deployment even further.
Deploying to Heroku
- Create a
Procfile
in your project root:
web: java -jar target/myapp.jar
- Create a Heroku application:
heroku create myapp
- Deploy your application:
git push heroku main
- Scale your application:
heroku ps:scale web=1
Best Practices for Spring Boot Deployment
Externalized Configuration
Use environment-specific configuration:
@Configuration
@PropertySource("classpath:application-${spring.profiles.active}.properties")
public class AppConfig {
// Configuration here
}
Health Checks and Monitoring
Add Spring Boot Actuator for health checks:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Configure health endpoints in application.properties
:
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always
Logging Configuration
Configure logging in application.properties
:
logging.level.root=WARN
logging.level.org.springframework=INFO
logging.level.com.myapp=DEBUG
logging.file.name=/var/log/myapp/application.log
JVM Optimization
Optimize JVM settings for production:
java -Xms512m -Xmx1024m -jar myapp.jar
Real-World Deployment Example
Let's walk through a complete real-world example of deploying a Spring Boot application to AWS with a CI/CD pipeline.
Sample Project Structure
myapp/
├── src/
├── pom.xml
├── Dockerfile
├── buildspec.yml
├── appspec.yml
└── scripts/
├── start_application.sh
└── stop_application.sh
CI/CD Pipeline with AWS CodePipeline
buildspec.yml
for AWS CodeBuild:
version: 0.2
phases:
install:
runtime-versions:
java: corretto17
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
build:
commands:
- echo Build started on `date`
- mvn clean package
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
- echo Writing image definitions file...
- aws cloudformation package --template-file template.yml --s3-bucket $S3_BUCKET --output-template-file outputtemplate.yml
artifacts:
files:
- outputtemplate.yml
- appspec.yml
- scripts/**/*
appspec.yml
for AWS CodeDeploy:
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: "myapp"
ContainerPort: 8080
Hooks:
- BeforeInstall: "scripts/stop_application.sh"
- AfterInstall: "scripts/start_application.sh"
- Start script (
start_application.sh
):
#!/bin/bash
aws ecs update-service --cluster my-cluster --service my-service --desired-count 2
- Stop script (
stop_application.sh
):
#!/bin/bash
aws ecs update-service --cluster my-cluster --service my-service --desired-count 0
Summary
In this guide, we've covered various deployment options for Spring Boot applications:
- JAR Deployment - The simplest approach with an embedded server
- WAR Deployment - For traditional application servers
- Docker Containerization - For container-based deployments
- Cloud Platform Deployment - For AWS, Azure, and GCP
- PaaS Deployment - For platforms like Heroku
Each approach has its advantages and best use cases. For modern applications, containerization and cloud deployments are increasingly popular due to their scalability and flexibility.
Remember that deployment is not just about making your application run on a server; it's about ensuring it runs reliably, securely, and efficiently in production. Always consider monitoring, logging, security, and performance optimization as part of your deployment strategy.
Additional Resources
- Spring Boot Deployment Documentation
- Docker Documentation
- AWS Elastic Beanstalk Documentation
- Azure Spring Apps Documentation
- Google App Engine Documentation
- Heroku Java Support
Exercises
- Deploy a simple Spring Boot application as a JAR file on your local machine.
- Create a Docker container for a Spring Boot application and run it locally.
- Set up a CI/CD pipeline for a Spring Boot application using GitHub Actions.
- Deploy a Spring Boot application to a free tier of a cloud provider (AWS, Azure, or GCP).
- Configure health checks and monitoring for your Spring Boot application using Actuator.
Happy deploying!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)