Topic 6.3
Spring Boot's Built-In Docker Support
In one line
Spring Boot has native, first-class Docker tooling built directly into Maven/Gradle — you don't always need to hand-write a Dockerfile at all.
Key ideas
- 01
Since Spring Boot 2.3, the Maven/Gradle plugin includes a built-in
build-imagegoal that uses Cloud Native Buildpacks to produce a production-ready, optimized container image DIRECTLY from your project — no Dockerfile required at all for a solid default setup. - 02
./mvnw spring-boot:build-image(Maven) or./gradlew bootBuildImage(Gradle) produces an image with sensible defaults baked in automatically: a layered jar structure (Topic 6.4 covers why layering matters), a reasonable JRE base, and container-aware JVM settings — genuinely competitive with a carefully hand-written multi-stage Dockerfile for many standard use cases. - 03
Spring Boot Actuator's
/actuator/healthendpoint (already built into most Spring Boot apps that include the actuator dependency) is the natural, idiomatic target for a Docker/Compose HEALTHCHECK — it can report DETAILED health (database connectivity, disk space, custom health indicators) rather than just 'is the process alive.' - 04
spring.docker.compose.enabled(Spring Boot 3.1+) is a genuinely delightful piece of built-in integration: if acompose.yamlfile exists in your project root, Spring Boot's DevTools can AUTOMATICALLY start the services it defines (like a database) when you run your app locally, and stop them when you stop the app — removing the need to manually rundocker compose upyourself during everyday local development. - 05
Spring Boot auto-detects certain well-known service images in a compose.yaml (like
postgres,redis,mongo) and automatically configures the corresponding connection properties for you — for these common cases, you may not even need to manually setSPRING_DATASOURCE_URLyourself; Spring Boot figures it out directly from the Compose file. - 06
None of this replaces understanding what's actually happening underneath (everything in Phases 1-5 is still exactly what's occurring) — but for day-to-day Spring Boot development, these tools remove a meaningful amount of manual Docker/Compose boilerplate.
In your stack
- →
This entire topic IS the Java angle — it's worth explicitly trying
./mvnw spring-boot:build-imageon any existing Spring Boot project you have and comparing the resulting image (size, layers viadocker history) against a hand-written multi-stage Dockerfile for the same app.
Code & diagrams
A production-ready image, without writing a single line of Dockerfile.
# Maven
./mvnw spring-boot:build-image
# Gradle
./gradlew bootBuildImage
# The resulting image is tagged automatically based on your project's
# artifactId/version (or configure a custom name in pom.xml/build.gradle)
docker run -p 8080:8080 myapp:0.0.1-SNAPSHOTWith spring.docker.compose.enabled (default true when this file is present), Spring Boot manages this FOR you during local dev.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: mydb
ports:
- "5432:5432"
# Just run your Spring Boot app locally (./mvnw spring-boot:run, or from your IDE) —
# DevTools detects this file and starts/stops "db" automatically alongside your app.
# No manual "docker compose up" needed during everyday development.Explain it without notes
What real problem does spring.docker.compose.enabled solve for everyday local development, compared to manually running docker compose up yourself?
Why might a team choose a hand-written multi-stage Dockerfile over spring-boot:build-image anyway, even though the latter requires less manual work?
Practice
Run spring-boot:build-image (or the Gradle equivalent) on any Spring Boot project and inspect the resulting image with docker history — compare its layer structure to a hand-written Dockerfile's layers.
Add a compose.yaml with a database service to a Spring Boot project, enable the Docker Compose support, and run the app locally without manually touching docker compose yourself — confirm the database container starts and stops automatically alongside your app.
Trade-offs
- ↔
Buildpacks-based images trade some explicit control for convenience and Spring-team-maintained best practices baked in automatically — a very reasonable default for many teams, though anyone with unusual base-image, OS-package, or compliance requirements will likely still prefer a hand-written Dockerfile they fully control.
Done when you can
I've tried spring-boot:build-image (or the Gradle equivalent) at least once and inspected its output.
I know Actuator's health endpoint is the natural target for a Docker healthcheck.
I understand spring.docker.compose.enabled automates dev-time container lifecycle, but doesn't replace understanding what Compose is doing underneath.