<p>I was using a DockerFile for building a spring boot jar file, uploads to artifactory and deploys to K8S. For doing this I wrote a standard Dockerfile like as shown below</p>
<pre><code>FROM maven:3.6.6-jdk-11 AS build
WORKDIR source
COPY . source
RUN mvn -q clean package -DskipTests


FROM maven:3.6.6-jdk-11
COPY --from=build source/app-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
RUN chmod +x app.jar
ENTRYPOINT [&quot;java&quot;,&quot;-jar&quot;,&quot;app.jar&quot;]
</code></pre>
<p>But I have seen a different project where they have mentioned like as shown below</p>
<pre><code>FROM maven:3.8.4-jdk-11 AS builder
WORKDIR source
COPY . .
RUN mvn -q clean package -DskipTests
RUN cp target/cdacapp-0.0.1-RELEASE.jar ./cdacapp.jar
RUN java -Djarmode=layertools -jar cdacapp.jar extract

FROM openjdk:11-jre-slim
WORKDIR application
COPY --from=builder source/dependencies/ ./
COPY --from=builder source/spring-boot-loader/ ./
COPY --from=builder source/webjars/ ./
COPY --from=builder source/application/ ./
ENTRYPOINT [ &quot;java&quot;, &quot;org.springframework.boot.loader.JarLauncher&quot;]
</code></pre>
<p>I would like to know what benefit we will get by running the application using JarLauncher</p>

Alex Man
<p>This setup produces an image that is smaller to download when you deploy an updated version of the image with just changed code, but not any of the changed dependencies.</p>
<p>A Docker image is made of <em>layers</em>, and in the setup you show here, each <code>COPY</code> command is a separate layer.  In the first form, the <code>COPY</code> with the fat jar produces a single layer, and if you change anything in the application you have to download that entire layer again (including all of the unchanged dependencies).  In the second form, though, if the <code>dependencies</code> and <code>spring-boot-loader</code> trees haven't changed (which is probably the common case) then only the later layers will need to be downloaded.</p>
<p>For a more practical example, let's say you're labeling your Docker images with a date stamp, and the most recent build was <code>registry.example.com/your-image:20220722</code>.  Now if you rebuild with the second Dockerfile</p>
<pre class="lang-bash prettyprint-override"><code>docker build -t registry.example.com/your-image:20220725 .
docker push registry.example.com/your-image:20220725
</code></pre>
<p>Docker will recognize that the registry already contains the &quot;dependencies&quot; layer and not push it again.  Similarly, if you update a Kubernetes manifest</p>
<pre class="lang-yaml prettyprint-override"><code>image: registry.example.com/your-image:20220725 # was 20220722
</code></pre>
<p>the cluster will download a piece of data called the <em>image manifest</em> and realize it already has the base layers, so it only needs to download the updated application layer at the end.</p>
<p>If you're working totally locally, there's not especially a benefit to one approach over the other.</p>
<p>The Spring Boot documentation has a section on <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/container-images.html#container-images" rel="nofollow noreferrer">Container Images</a> which discusses this specific approach further.</p>
