Skip to main content

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:

  1. JAR Deployment - Spring Boot's embedded server approach
  2. WAR Deployment - Traditional servlet container approach
  3. Containerization - Using Docker and similar technologies
  4. Cloud Platform Deployment - Using AWS, Azure, Google Cloud, etc.
  5. 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:

bash
mvn clean package

With Gradle:

bash
./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:

bash
java -jar target/myapp-0.0.1-SNAPSHOT.jar

You can also specify configuration properties:

bash
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:

  1. Create a service file:
bash
sudo nano /etc/systemd/system/myapp.service
  1. 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
  1. Enable and start the service:
bash
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

  1. Update your pom.xml (Maven):
xml
<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>
  1. Extend SpringBootServletInitializer:
java
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);
}
}
  1. Build the WAR file:
bash
mvn clean package
  1. 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

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:

dockerfile
FROM openjdk:17-jdk-slim
VOLUME /tmp
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

Building and Running a Docker Image

  1. Build the Docker image:
bash
docker build -t myapp:latest .
  1. Run the Docker container:
bash
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:

yaml
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:

bash
docker-compose up

Cloud Platform Deployment

Modern applications are often deployed to cloud platforms, providing scalability and reliability.

AWS Elastic Beanstalk

  1. Package your application as a JAR file
  2. Create an Elastic Beanstalk application through AWS Console or CLI
  3. Upload your JAR file
  4. Elastic Beanstalk automatically provisions resources and deploys your application

Example using the AWS CLI:

bash
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:

  1. Create an app.yaml file:
yaml
runtime: java17
instance_class: F2
  1. Deploy using the Google Cloud SDK:
bash
gcloud app deploy

Microsoft Azure

To deploy to Azure App Service:

  1. Install the Azure CLI
  2. Log in and create a resource group:
bash
az login
az group create --name myResourceGroup --location eastus
  1. Create an App Service plan:
bash
az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku FREE
  1. Create a web app:
bash
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name mywebapp --runtime "JAVA:17-java17"
  1. Deploy your JAR file:
bash
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

  1. Create a Procfile in your project root:
web: java -jar target/myapp.jar
  1. Create a Heroku application:
bash
heroku create myapp
  1. Deploy your application:
bash
git push heroku main
  1. Scale your application:
bash
heroku ps:scale web=1

Best Practices for Spring Boot Deployment

Externalized Configuration

Use environment-specific configuration:

java
@Configuration
@PropertySource("classpath:application-${spring.profiles.active}.properties")
public class AppConfig {
// Configuration here
}

Health Checks and Monitoring

Add Spring Boot Actuator for health checks:

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

Configure health endpoints in application.properties:

properties
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always

Logging Configuration

Configure logging in application.properties:

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:

bash
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

  1. buildspec.yml for AWS CodeBuild:
yaml
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/**/*
  1. appspec.yml for AWS CodeDeploy:
yaml
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"
  1. Start script (start_application.sh):
bash
#!/bin/bash
aws ecs update-service --cluster my-cluster --service my-service --desired-count 2
  1. Stop script (stop_application.sh):
bash
#!/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:

  1. JAR Deployment - The simplest approach with an embedded server
  2. WAR Deployment - For traditional application servers
  3. Docker Containerization - For container-based deployments
  4. Cloud Platform Deployment - For AWS, Azure, and GCP
  5. 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

Exercises

  1. Deploy a simple Spring Boot application as a JAR file on your local machine.
  2. Create a Docker container for a Spring Boot application and run it locally.
  3. Set up a CI/CD pipeline for a Spring Boot application using GitHub Actions.
  4. Deploy a Spring Boot application to a free tier of a cloud provider (AWS, Azure, or GCP).
  5. 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! :)