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.

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, Redis, and MongoDB.

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 — no credit card required.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also