How to deploy a Spring Boot application with Docker and Java 21
- Dockerfile
- Build and run the image
- Error without repackaging
- Alpine image size
- Healthcheck potential issue with Docker compose
- Add more parameters to the Spring application
Dockerfile
For our image we use the eclipse temurin alpine JRE distribution.
Eclipse Temurin is a de facto standard for Java development and doesn't present licensing surpises ;-)
To deploy we use simply a JRE distribution, generally we don't need a JDK.
And we use Alpine Linux as base image, this is minimalistic and fast. If you need more features you can opt for a different Linux distribution.
We copy the jar file to the /opt directory as suggested by the FHS
## alpine linux with JRE
FROM docker pull eclipse-temurin:21-jre-alpine
## create a nonroot user and group
RUN addgroup -S spring && adduser -S spring -G spring
## copy the spring jar
COPY target/*.jar /opt/myApp.jar
## set the nonroot user as the default user
USER spring:spring
## set the working directory
WORKDIR /opt
ENTRYPOINT ["java", "-jar", "myApp.jar"]
## expose the port to the external world
EXPOSE 8080
To have a runnable jar you need to repackage the default jar.
Here you can find the official documentation:
spring-boot:repackage
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Build and run the image
You can build your Dockerfile with e.g.:
docker build -t spring-example .
and run it with:
docker run -it -p 8080:8080 spring-example
Error without repackaging
If you get this error no main manifest attribute, in [name of your app]
something went wrong with the spring-boot-maven-plugin
.
Verifiy that it is correctly configured.
Alpine image size
The alpine image size is smaller compared to other distributions.
The version with JRE (21 -jre-alpine) is 66MB.
Healthcheck potential issue with Docker compose
If you are using Docker compose and you add an healthcheck to check if your image started correctly before to start the next container you need to test with wget
and not curl
.
curl
is not available in this image, if you want use it you need to install it manually.
Example of healthcheck in Docker Compose:
services:
my-app:
build:
context: ../app-backend/target
dockerfile: Dockerfile
ports:
- "8080:8080"
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1
interval: 1m30s
timeout: 10s
retries: 3
Here is an explanation of the wget options used:
- --no-verbose: this option turns off verbose mode, which means
wget
's output will be minimized. This may be desired so as not to clog up your logs with unnecessary data. - --tries=1: this option sets the number retries to 1.
wget
will retry network operations if they failed due to temporary network errors. - --spider:
wget
will not download the pages, just check that they are there. This is known as spider mode. This is useful for checking link validity.
Add more parameters to the Spring application
If you want to add more start parameters to your Spring application you can add them to the ENTRYPOINT:
Example of ENTRYPOINT with more Spring Boot parameters:
ENTRYPOINT ["java", \
"-Dspring.profiles.active=dev", \
"-XX:InitialRAMPercentage=50", \
"-XX:MaxRAMPercentage=80", \
"-jar", "/opt/myApp.jar"]