Updated August 2026 — full tutorial restored for this URL.
A multi-stage Dockerfile builds your Spring Boot JAR in a JDK image, then copies only the JAR into a slim JRE image. Here we pair it with PostgreSQL.
Companion: Spring Boot + MySQL with Docker.
1. Why multi-stage
- Final image has no Maven/Gradle caches or source
- Smaller attack surface and faster pulls
- Same Dockerfile works in CI
2. Multi-stage Dockerfile
FROM eclipse-temurin:21-jdk AS build
WORKDIR /workspace
COPY mvnw pom.xml ./
COPY .mvn .mvn
RUN ./mvnw -q -DskipTests dependency:go-offline
COPY src src
RUN ./mvnw -q -DskipTests package
FROM eclipse-temurin:21-jre AS runtime
WORKDIR /app
RUN useradd -r spring
USER spring
COPY --from=build /workspace/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-XX:+UseContainerSupport","-jar","/app/app.jar"]
3. Spring datasource for Postgres
spring.datasource.url=jdbc:postgresql://postgres:5432/appdb
spring.datasource.username=app
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
4. Compose with PostgreSQL
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: appdb
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
ports: ["5432:5432"]
volumes: ["pgdata:/var/lib/postgresql/data"]
api:
build: .
ports: ["8080:8080"]
depends_on: [postgres]
volumes:
pgdata:
5. Tips
- Layer dependency download before copying
srcfor faster rebuilds. - Pass secrets via env / Compose secrets, not baked into the image.
- Add a healthcheck on Postgres before starting Flyway-heavy apps.