gs-spring-boot-docker: a getting started Docker guide for Spring Boot
Spring Boot with Docker :: Learn how to create a Docker container from a Spring Boot application with Maven or Gradle
At a glance
- What is it?
- The Spring guide gs-spring-boot-docker walks a Java 17 Spring Boot application from a plain Dockerfile to a layered image that runs as a non-root user, and it is deliberately narrow in scope, with a separate topical guide covering the choices it leaves out.
- Who is it for?
- gs-spring-boot-docker fits a developer meeting Spring Boot for the first time who needs a working image in an afternoon, or a team that wants one shared, reviewable Dockerfile rather than a private variant. It does not fit production hardening, since the guide says itself that the scope is limited to a few basic needs and that a production image has many considerations a short guide cannot cover.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 23 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A narrow guide that says so in the first paragraph
The guide opens by stating its own limits. It walks through building a Docker image for a Spring Boot application, starting with a basic Dockerfile and making a few tweaks, then shows a couple of options that use build plugins for Maven and Gradle instead of calling docker directly. Then it names the scope: this is a getting started guide, so the scope is limited to a few basic needs, and if you are building container images for production use there are many things to consider that it is not possible to cover in a short guide. That candour is a design feature rather than an apology. A reader who wants a hardened production image is sent to a separate topical guide on Docker that covers a wider range of choices in more detail, and the README points there too. The repository itself is Apache-2.0 licensed, with LICENSE.txt and a separate LICENSE.writing.txt for the prose, and the last push was on 2026-09-30.
The four line Dockerfile that runs the jar
The core artefact of the guide is the Dockerfile, and the first version is four instructions. The base image is eclipse-temurin:17, matching the Java 17 prerequisite the guide asks for, a build argument names the jar to copy, the jar is copied in as app.jar, and the entry point launches it:
FROM eclipse-temurin:17
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]The comment in the guide explains the array form of ENTRYPOINT: it is used so that there is no shell wrapping the Java process, which matters when you later pass signals to the container or read its output. The build argument exists because the jar path differs between build tools, and the guide shows the two variants. With Gradle the jar is in build/libs, so the build passes a build argument, while with Maven the default of target/*.jar is already right:
docker build --build-arg 'JAR_FILE=build/libs/*-SNAPSHOT.jar' -t springio/gs-spring-boot-docker .The image is tagged springio/gs-spring-boot-docker in both cases.
Running as a non-root user with addgroup and adduser
The guide's main improvement is privilege. It argues that running applications with user privileges helps mitigate some risks, and then shows how to do it in the same base image by creating a system group and user, and switching to it before the jar is copied and run:
RUN addgroup --system spring && adduser --system --ingroup spring spring
USER spring:springThe rest of the file stays the same, and the guide shows how to see the result. Running the container produces a startup log entry that names the user, and the sample shows the application starting with PID 1 and the note that the jar was started by spring in /. That line is the check: if the log says started by spring, the image is running unprivileged, and if it says root, the USER instruction was not applied. The ordering matters too, since the USER instruction has to come before the entry point so the process itself, not just the shell, runs as that user.
The entropy note that is no longer needed
One paragraph in the guide covers a fix that has since become unnecessary, and it is worth reading because the reason still applies. The guide used to add a system property pointing at /dev/urandom as a source of entropy, to reduce Tomcat startup time, but it notes that this is not necessary anymore with JDK 8 or later, citing the JDK change that removed the need for it. The current container therefore has no such property. What survives from that paragraph is the practice of checking the base image and the JDK behaviour rather than copying a workaround from an older tutorial, and the general point about container images inheriting the defaults of whatever runtime sits underneath them.
Layering the fat jar so dependencies stop invalidating the cache
The last mechanical trick the guide teaches is layering. A Spring Boot fat JAR has a clean separation between dependencies and application resources, and the guide uses that fact to improve performance by creating layers in the container filesystem. The reasoning is about caching: the layers are cached both at build time and at runtime in most runtimes, so the frequently changing resources, which are the class files and static resources, should sit in a layer above the dependencies that rarely change. Without layering, every code change rewrites the dependency layer and the cache buys nothing. The guide frames this as an optimisation of the image, not as a functional requirement, which is the right order: the image runs without it, and it pays off on a project that rebuilds often.
Build plugins instead of calling docker yourself
Beyond the Dockerfile, the guide shows a couple of options that use build plugins for Maven and Gradle rather than invoking docker from the command line. The approach is the same in both build tools: instead of packaging a jar and then copying it into an image, the plugin drives the container build itself and wires the artifact into it. The practical difference is where the jar is produced and who knows about its path. With a manual docker build, the path of the jar is a fact your build command has to know, which is why the Gradle variant needs an explicit build argument while Maven does not. With a plugin, the build tool owns the artifact path and the container step becomes part of the same build. That also means the image build happens as part of your normal build lifecycle, which is convenient in CI and one more reason to make sure the image step is something you can turn off when you only want to compile.
Where the project comes from: Initializr, then the complete/ directories
The guide does not assume you have a project. It offers a pre-initialised project on Spring Initializr, configured with the Gradle build, JVM version 17, jar packaging, the group id com.example, the artifact id spring-boot-docker, the package name hello and the Spring Web dependency, and it walks the manual path too: choose Gradle or Maven, pick Spring Web among the dependencies, click Generate and download the ZIP. The application itself is a single class at src/main/java/hello/Application.java, or the Kotlin equivalent at src/main/kotlin/hello/Application.kt, annotated with @SpringBootApplication and @RestController, with @RequestMapping mapping / to a home method that sends the Hello World response, and a main method that calls SpringApplication.run(), or runApplication in Kotlin. The repository mirrors that structure with initial/ and complete/ directories for the Java variant and initial-kotlin/ and complete-kotlin/ for the Kotlin one, so the before and after states of the project are visible side by side.
Running the app before and after the container
The guide asks you to run the application in the host operating system first, so that a failure inside the container is not confused with a broken application. With Gradle that is a build followed by running the jar directly, and with Maven it is the packaging step followed by the same:
./mvnw package && java -jar target/spring-boot-docker-complete-0.0.1-SNAPSHOT.jarEither way the result is the Hello Docker World message on localhost:8080. After containerising, the run command maps the port and starts the image:
docker run -p 8080:8080 springio/gs-spring-boot-dockerThe port mapping is the same 8080 in both cases, which is deliberate. It means the client code, the tests and the browser do not change when the application moves from a local process to a container, and it isolates the real difference, which is the image and the user it runs as.
Editorial conclusion
gs-spring-boot-docker fits a developer meeting Spring Boot for the first time who needs a working image in an afternoon, or a team that wants one shared, reviewable Dockerfile rather than a private variant. It does not fit production hardening, since the guide says itself that the scope is limited to a few basic needs and that a production image has many considerations a short guide cannot cover. Before following it, read the Dockerfile rather than copying it, because the guide also shows a deliberately insecure first version next to the non-root one, and use the topical guide on Docker for the decisions this guide leaves open, including whether to build the jar inside the image with a build plugin or outside it with docker build.
Frequently asked questions
What does the gs-spring-boot-docker guide cover?
It walks through building a Docker image for a Spring Boot application, starting from a basic Dockerfile and adding a few tweaks, and it also shows options that use Maven and Gradle build plugins instead of calling docker. The guide states that it is a getting started guide with a limited scope, and points to a separate topical guide on Docker for a wider range of choices.
What Dockerfile does the gs-spring-boot-docker guide use?
It starts from eclipse-temurin:17, takes the jar through an ARG and COPY it in as app.jar, and runs it with ENTRYPOINT ["java","-jar","/app.jar"] so there is no shell wrapping the process. The improved version adds a spring system group and user and switches to it with USER spring:spring before the copy.
Which Java version does the gs-spring-boot-docker guide use?
Java 17, which the prerequisites ask for and which the pre-initialised Initializr project sets, matching the eclipse-temurin:17 base image in the Dockerfile.
How do I build and run the containerised Spring Boot app?
Build with docker build -t springio/gs-spring-boot-docker . and start it with docker run -p 8080:8080 springio/gs-spring-boot-docker, then open localhost:8080. With Gradle the build also passes a build argument because the jar sits in build/libs rather than target.
Does the gs-spring-boot-docker guide cover production container images?
No. It says it is a getting started guide with a limited scope, and that building images for production use has many considerations a short guide cannot cover, so it points to the topical guide on Docker for the wider range of choices.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/spring-guides-gs-spring-boot-docker)Was this useful?