A Docker image
Docker packages an application together with its environment — the right Java version and system settings — into an image. You start a container from the image, and it runs the same on your laptop, on a server and in the cloud. Spring Boot offers two ways to get an image: write a short Dockerfile or let the Maven plugin build it. This lesson needs Docker installed.
A Dockerfile
Create a file in the project root, next to pom.xml:
# Dockerfile
FROM eclipse-temurin:25-jre
WORKDIR /app
COPY target/blog-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]| Line | Meaning |
|---|---|
FROM eclipse-temurin:25-jre | The base — Linux with Java 25 (runtime only, no compiler) |
WORKDIR /app | The working folder inside the image |
COPY ... | Puts the built JAR into the image |
EXPOSE 8080 | A hint that the application listens on port 8080 |
ENTRYPOINT | The container's start command |
Build the JAR first, then the image, and run a container:
./mvnw clean package
docker build -t blog .
docker run -p 8080:8080 blog-t blog names the image, -p 8080:8080 links your computer's port to the container's port. The blog opens at http://localhost:8080, as before.
Without a Dockerfile
The Spring Boot plugin can build an image itself with Cloud Native Buildpacks:
./mvnw spring-boot:build-image
docker run -p 8080:8080 docker.io/library/blog:0.0.1-SNAPSHOTThe plugin picks Java from java.version in pom.xml and splits the JAR into layers: libraries apart from your code. Rebuilding after a code change is then faster.
Together with the database
On a server the application needs PostgreSQL. Both containers are handy to describe in one file:
# compose.yaml
services:
db:
image: postgres:18
environment:
POSTGRES_DB: blog
POSTGRES_USER: blog
POSTGRES_PASSWORD: changeme
app:
image: blog
ports:
- "8080:8080"
environment:
SPRING_PROFILES_ACTIVE: prod
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/blog
SPRING_DATASOURCE_USERNAME: blog
SPRING_DATASOURCE_PASSWORD: changeme
depends_on:
- dbdocker compose up starts both containers. Settings are passed as environment variables — just as in the previous lesson. The real password is not written into the file: on a server it comes from secrets or from a .env file that stays out of Git.
Common mistake
Inside a container localhost is the container itself, not your computer and not the database container. With the address jdbc:postgresql://localhost:5432/blog the application does not start:
Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.In compose.yaml the database is reached by its service name — db, as in the example above.