Back to Blog
Tutorial8 min read2026-05-01

How to Deploy a Spring Boot Application with Docker

Containerise a Spring Boot Java application with a multi-stage Dockerfile and deploy it to PandaStack with GitHub-triggered CI/CD.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Deploy Spring Boot to the Cloud with Docker

Spring Boot is the dominant Java framework for building production-grade REST APIs and microservices. It comes with an embedded Tomcat server, production-ready health endpoints via Spring Actuator, and seamless integration with PostgreSQL, MySQL, and Redis.

PandaStack runs Docker containers and supports all the databases Spring Boot typically needs. This guide covers a complete deployment from a fresh Spring Boot project to a live production URL.

Prerequisites

  • Java 21+ (JDK) installed locally
  • Maven or Gradle installed locally
  • Docker installed locally
  • A GitHub account
  • PandaStack CLI: npm install -g @pandastack/cli

Step 1 — Create a Spring Boot Application

Use Spring Initializr via the CLI:

curl https://start.spring.io/starter.tgz   -d dependencies=web,actuator,data-jpa,postgresql   -d javaVersion=21   -d bootVersion=3.3.0   -d artifactId=my-spring-app   -d name=MySpringApp   | tar -xzvf -
cd my-spring-app

Or generate from [start.spring.io](https://start.spring.io) with Spring Web, Spring Boot Actuator, Spring Data JPA, and PostgreSQL Driver.

Add a health and hello endpoint in src/main/java/com/example/MySpringApp/HelloController.java:

package com.example.myspringapp;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@RestController
public class HelloController {

    @GetMapping("/api/hello")
    public Map<String, String> hello() {
        return Map.of("message", "Hello from PandaStack!");
    }
}

Spring Actuator already exposes /actuator/health — use that as the health check endpoint.

Step 2 — Build the Application

./mvnw package -DskipTests
ls target/*.jar
# target/my-spring-app-0.0.1-SNAPSHOT.jar

Step 3 — Write a Multi-Stage Dockerfile

A multi-stage build keeps the final image small by separating the build environment from the runtime:

# Stage 1: Build
FROM eclipse-temurin:21-jdk-alpine AS builder

WORKDIR /app

COPY .mvn/ .mvn/
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline -q

COPY src ./src
RUN ./mvnw package -DskipTests -q

# Stage 2: Runtime
FROM eclipse-temurin:21-jre-alpine

WORKDIR /app

RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

COPY --from=builder /app/target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

The runtime image uses the JRE (not JDK) and a non-root user — both production best practices.

Build and test locally:

docker build -t my-spring-app .
docker run -p 8080:8080   -e SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/mydb   my-spring-app
curl http://localhost:8080/actuator/health
# {"status":"UP"}

Step 4 — Configure pandastack.json

{
  "type": "container",
  "healthCheckPath": "/actuator/health"
}

Spring Actuator's /actuator/health returns {"status":"UP"} with HTTP 200 when the application is ready — perfect for PandaStack's health check.

Step 5 — Configure Application Properties

Create src/main/resources/application-production.properties:

spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false
management.endpoints.web.exposure.include=health,info

Activate the profile via environment variable in the PandaStack dashboard:

SPRING_PROFILES_ACTIVE=production
DATABASE_URL=jdbc:postgresql://your-pandastack-db-host:5432/mydb
DB_USERNAME=spring_user
DB_PASSWORD=your-secure-password

Step 6 — Provision a PostgreSQL Database

panda db create --type postgres --name spring-db

PandaStack adds connection details to your project's environment automatically.

Step 7 — Push to GitHub and Deploy

git init
git add .
git commit -m "Spring Boot app with Docker and PandaStack config"
gh repo create my-spring-app --private --source=. --push

Deploy:

panda deploy

Or connect at [dashboard.pandastack.io](https://dashboard.pandastack.io) → New Project → select your GitHub repository.

Verify the Deployment

curl https://my-spring-app.pandastack.io/actuator/health
# {"status":"UP"}

curl https://my-spring-app.pandastack.io/api/hello
# {"message":"Hello from PandaStack!"}

panda logs --follow

Step 9 — Understand Spring Actuator Endpoints

Spring Actuator exposes several useful endpoints in production. The /actuator/health endpoint is used by PandaStack for health checks, but you can also expose /actuator/info and /actuator/metrics for observability. Control which endpoints are exposed in application-production.properties:

management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=when-authorized

The health endpoint returns component-level status including database connectivity:

{
  "status": "UP",
  "components": {
    "db": { "status": "UP" },
    "diskSpace": { "status": "UP" }
  }
}

If the database is unreachable, the health check returns DOWN with HTTP 503 — PandaStack will not route traffic to an unhealthy instance.

Summary

Spring Boot on PandaStack uses a multi-stage Docker build to produce a lean, secure runtime image. Spring Actuator provides the health check endpoint out of the box. Set database credentials in the PandaStack dashboard and push to GitHub — deploys happen automatically. Full docs at [docs.pandastack.io](https://docs.pandastack.io).

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also