Search code examples
javaspring-bootmavendocker

How to write a dockerfile to add maven build on existing spring boot project which contains jdk


My Boss is went to holiday for some days, I am a java developer I dont know much about docker (Only basic knowledge)

I have the java Spring boot project , in that there is a Dockerfile at the root of the project.

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

I want to add maven into the same, without modifiying the structure. and maven should clean package it.?

for eg. docker build -t user/myimage .

it should install maven and clean package my project automatically. without I need to run mvn clean package explicitly

I have got few resources before from stackoverflow but I cannot do experiment, I need code which can run thought the given jdk script mentioned previously.

FROM maven:3.6.0-jdk-11-slim AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package

I request to you please give a equivalent script for Maven clean package so I can add it to the dockerfile which build my image.


Solution

  • I have got few resources before from stackoverflow but I cannot do experiment, I need code which can run thought the given jdk script mentioned previously.

    If I understand well, your issue is you want to add the maven packaging step in the docker build while still using that exact version of JDK : FROM openjdk:8-jdk-alpine at runtime and to not depend on that base image : FROM maven:3.6.0-jdk-11-slim AS build.

    First thing : don't worry to depend on another base docker image in a Docker Build.
    Docker build has a multi-stage build feature since the 17.05 Docker version (05/2017), which allows to define multiple stages in a build and that suits to your need.
    Indeed, in the first stage you could rely on the maven docker image to build your application while in the second stage you could rely on the JDK docker image to run your application.
    The multi-stage build feature has also another advantage : image size optimization since intermediate layers produced by previous steps are not kept in the final image size.
    For integration/production like environment, that is probably the way that I would use.

    To come back to your issue, if you want to use the answer that you linked, the main thing that you need to change is the JDK tag of the final base image to match your requirement and you should also adapt some small things.
    As a side note, currently you copy the JAR at the root of the image. That is not a good practice for security reasons. You should rather copy it in a folder, for example /app.

    When you reference the jar built by maven, it is also preferable to prefix the jar by its artifactId/final name without its version rather than consider any jar in the target folder as the fat jar as you do here : ARG JAR_FILE=target/*.jar.

    So it would give :

    # Build stage
    FROM maven:3.6.0-jdk-11-slim AS build
    COPY pom.xml /app/
    COPY src /app/src
    RUN mvn -f /app/pom.xml clean package
    
    # Run stage
    FROM openjdk:8-jdk-alpine # Use your target JDK here !
    COPY --from=build /app/target/app*.jar /app/app.jar
    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]
    

    Note that the proposed solution is very simple, is enough in many cases but may not suit to your specific context.
    There are really several approaches to handle your question. According to your targeted environment, your requirements are not the same and the strategy will differ.
    These requirements may be build speed, final image size optimization, fast feedback for local developers. And all of these are not necessarily compatible.
    The Docker build area is really a very large subject. I strongly advise you to study more that to be able to adjust the docker build solution to your real needs.