Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/spring-projects/spring-boot/llms.txt

Use this file to discover all available pages before exploring further.

Spring Boot’s executable JAR and WAR packaging options work across a wide range of deployment targets. This guide covers the most common production destinations and shows you the configuration each one requires.

Deploy as a Docker container

Spring Boot integrates with Cloud Native Buildpacks (CNB) to produce optimized OCI images without writing a Dockerfile. When you need more control, you can write your own Dockerfile instead.

Deploy to Kubernetes

Spring Boot auto-detects Kubernetes deployment environments by checking for *_SERVICE_HOST and *_SERVICE_PORT environment variables. The Actuator module exposes dedicated liveness and readiness endpoints that Kubernetes uses to manage pod lifecycle.

Add Actuator health probes

Add spring-boot-starter-actuator to your dependencies, then enable Kubernetes probes:
application.properties
management.endpoint.health.probes.enabled=true
management.health.livenessstate.enabled=true
management.health.readinessstate.enabled=true

Sample Kubernetes Deployment manifest

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: docker.io/library/myapp:0.0.1-SNAPSHOT
          ports:
            - containerPort: 8080
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 5
          lifecycle:
            preStop:
              sleep:
                seconds: 10
The preStop sleep hook shown above requires Kubernetes 1.32 or later. On earlier versions, use an exec command instead:
lifecycle:
  preStop:
    exec:
      command: ["sh", "-c", "sleep 10"]
This sleep gives the load balancer time to stop routing new requests to the pod before Spring Boot’s graceful shutdown begins.

Graceful shutdown configuration

Configure Spring Boot’s graceful shutdown period to match your Kubernetes termination grace period:
application.properties
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=30s
If you increase spring.lifecycle.timeout-per-shutdown-phase beyond 30 seconds, you must also increase terminationGracePeriodSeconds in your pod spec. Otherwise, Kubernetes sends SIGKILL before Spring Boot has finished shutting down in-flight requests.

Deploy as a WAR to a traditional servlet container

WAR deployment is not supported for Spring WebFlux applications because WebFlux does not depend on the servlet API.
1

Extend SpringBootServletInitializer

Update your main application class to extend SpringBootServletInitializer and override configure:
MyApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@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);
    }

}
2

Change the packaging to WAR

pom.xml
<packaging>war</packaging>
3

Mark the embedded container as provided

The embedded Tomcat (or Jetty/Undertow) must not be bundled into the WAR since the external container provides it.
pom.xml
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
  </dependency>
</dependencies>
4

Build and deploy the WAR

# Maven
./mvnw package
cp target/myapp-0.0.1-SNAPSHOT.war $TOMCAT_HOME/webapps/

# Gradle
./gradlew war
cp build/libs/myapp-0.0.1-SNAPSHOT.war $TOMCAT_HOME/webapps/
When built with the Spring Boot plugin, the WAR file is also executable via java -jar, because lib-provided dependencies are packaged separately. You can run it on the command line and deploy it to a container with the same artifact.

Install as a Linux systemd service

Running Spring Boot as a systemd service gives you automatic restart on failure, log management through journald, and controlled startup ordering.
1

Place the JAR in a stable location

sudo mkdir -p /var/myapp
sudo cp target/myapp-0.0.1-SNAPSHOT.jar /var/myapp/myapp.jar
sudo useradd -r -s /bin/false myapp
sudo chown -R myapp:myapp /var/myapp
2

Create the systemd unit file

Create /etc/systemd/system/myapp.service:
myapp.service
[Unit]
Description=myapp
After=syslog.target network.target

[Service]
User=myapp
Group=myapp

Type=exec
ExecStart=/path/to/java/home/bin/java -jar /var/myapp/myapp.jar
WorkingDirectory=/var/myapp
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
Customize Description, User, Group, ExecStart, and WorkingDirectory for your application. The SuccessExitStatus=143 entry tells systemd that exit code 143 (SIGTERM) is a normal termination, not a failure.
3

Enable and start the service

sudo systemctl daemon-reload
sudo systemctl enable myapp.service
sudo systemctl start myapp.service
sudo systemctl status myapp.service

Deploy to Cloud Foundry

Cloud Foundry’s Java buildpack has first-class support for Spring Boot executable JARs.
1

Build your application

./mvnw clean package
2

Log in and push

cf login -a https://api.your-cf-instance.com
cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
3

Verify the deployment

cf apps
You will see output similar to:
name                  requested state   instances   memory   disk   urls
acloudyspringtime     started           1/1         512M     1G     acloudyspringtime.cfapps.io
If your Cloud Foundry environment routes traffic through trusted proxies, forward headers are enabled automatically. If your platform does not guarantee that application instances are only accessible from a trusted network, set spring.forward-headers-strategy=none to avoid header spoofing.
Cloud Foundry exposes service binding credentials as environment variables prefixed with vcap. Spring Boot flattens these into the Spring Environment so you can access them with standard @Value or @ConfigurationProperties bindings.

Other cloud platforms

Elastic Beanstalk supports two options for Spring Boot:Spring Boot auto-detects AWS ECS environments by checking for the AWS_EXECUTION_ENV variable. Override detection with the spring.main.cloud-platform property if needed.
Create an app.yaml in src/main/appengine/:
app.yaml
service: "default"

runtime: "java17"
env: "flex"

handlers:
- url: "/.*"
  script: "this field is required, but ignored"

manual_scaling:
  instances: 1

health_check:
  enable_health_check: false
Deploy with the App Engine Maven plugin:
pom.xml
<plugin>
  <groupId>com.google.cloud.tools</groupId>
  <artifactId>appengine-maven-plugin</artifactId>
  <version>2.4.4</version>
  <configuration>
    <project>myproject</project>
  </configuration>
</plugin>
mvn appengine:deploy
Create a Procfile at the root of your repository that passes the $PORT environment variable:
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Deploy by pushing to the Heroku remote:
git push heroku main

Build docs developers (and LLMs) love