A Spring Boot app deploys on Hangar from its repository, built with Maven or Gradle into a jar and run as a long-lived JVM. No Dockerfile is needed.
Before you start
- A Spring Boot project in a Git repository, with
pom.xmland the Maven wrapper, orbuild.gradleandgradlew, at the root. - A Hangar account.
1. Create the service
Create a project, add a service and pick your repository and branch. Choose a region and leave the builder on Automatic. It detects Maven or Gradle, builds the project with JDK 21 and starts the jar with java -jar, passing PORT to Spring as server.port.
To build with another JDK, set it in the Variables tab:
RAILPACK_JDK_VERSION=17
2. Set the variables
The start command reads PORT, which Hangar sets to the domain's container port. Add your own configuration in the Variables tab:
JAVA_OPTS=-XX:MaxRAMPercentage=75
JAVA_OPTS is passed to the JVM. MaxRAMPercentage sizes the heap from the service's memory limit, leaving room for the rest of the JVM, instead of the JVM's conservative default.
3. Deploy and add a domain
Deploy the service. In Settings → Networking, add a domain with container port 8080 and HTTPS on.
Spring Boot sits behind Hangar's proxy, which terminates HTTPS. So that redirects and generated links use https://, add to application.properties:
server.forward-headers-strategy=framework
Adding PostgreSQL
Add a PostgreSQL service in the same project and region. From its internal connection details, set on the app:
SPRING_DATASOURCE_URL=jdbc:postgresql://<host>:5432/<database>
SPRING_DATASOURCE_USERNAME=<user>
SPRING_DATASOURCE_PASSWORD=<password>
Spring Boot maps these variables to spring.datasource.* on its own. JDBC URLs do not take the postgresql://user:password@ form, which is why the credentials go in their own variables.
Flyway or Liquibase migrations run when the app starts, before it accepts traffic, as they do locally.
Health checks
With Spring Boot Actuator on the classpath, /actuator/health reports when the app is ready. The service's health check, in Settings → Scaling, is a command run inside the container, so it can call that endpoint if the image has a client for it:
curl -fs http://localhost:8080/actuator/health
Give it a start period long enough for the JVM to boot, such as 60 seconds, so a new deployment only takes traffic once Spring has started.
Troubleshooting
- 502 on the domain: a
PORTvariable you set differs from the container port. Remove it, or make the two match. - The container is killed with exit code 137: the JVM uses more memory than the service's limit. Lower
MaxRAMPercentageor raise the limit. - Redirects go to
http://:server.forward-headers-strategyis missing.