Search code examples
javamavendockerpom.xmlmicroservices

multi-module Maven project on Dockers


I have a multi-module maven project where the single modules are all runnable microservice applications containing their own Dockerfile, so in production every module will be a containerized application.

The parent project, which contains the child-modules only contains the parent pom.xml and the docker-compose.yml

I have tried to use the following Dockerfile (on sub-module level):

FROM sgrio/java-oracle

RUN apt-get update

RUN apt-get install -y maven

COPY ../pom.xml /usr/local/service/Oogaday/pom.xml

COPY pom.xml /usr/local/service/Oogaday/OogadayApi/pom.xml

COPY src /usr/local/service/Oogaday/OogadayApi/src

WORKDIR /usr/local/service/Oogaday/OogadayApi/

RUN mvn package -DskipTests

CMD ["java","-jar","org.oogaday.api-1.0-SNAPSHOT-jar-with-dependencies.jar"]

But I am getting a security error because I am trying to copy the parent pom.xml file (which is not placed in the directory from which I am running the build).

So is there a way to build a maven based sub-module with parent pom?


Solution

  • This is my suggestion, you should take advantage the more you can of docker cache.

    Assume this multi-module project pom layout:

    +-- my-project
       +-- module1
       |   `-- pom.xml
       +-- module2
       |   `-- pom.xml
        `- pom.xml
    

    Dockerfile:

    # cache as most as possible in this multistage dockerfile.
    FROM maven:3.6-alpine as DEPS
    
    WORKDIR /opt/app
    COPY module1/pom.xml module1/pom.xml
    COPY module2/pom.xml module2/pom.xml
    
    # you get the idea:
    # COPY moduleN/pom.xml moduleN/pom.xml
    
    COPY pom.xml .
    RUN mvn -B -e -C org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline
    
    # if you have modules that depends each other, you may use -DexcludeArtifactIds as follows
    # RUN mvn -B -e -C org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline -DexcludeArtifactIds=module1
    
    # Copy the dependencies from the DEPS stage with the advantage
    # of using docker layer caches. If something goes wrong from this
    # line on, all dependencies from DEPS were already downloaded and
    # stored in docker's layers.
    FROM maven:3.6-alpine as BUILDER
    WORKDIR /opt/app
    COPY --from=deps /root/.m2 /root/.m2
    COPY --from=deps /opt/app/ /opt/app
    COPY module1/src /opt/app/module1/src
    COPY module2/src /opt/app/module2/src
    
    # use -o (--offline) if you didn't need to exclude artifacts.
    # if you have excluded artifacts, then remove -o flag
    RUN mvn -B -e -o clean install -DskipTests=true
    
    # At this point, BUILDER stage should have your .jar or whatever in some path
    FROM openjdk:8-alpine
    WORKDIR /opt/app
    COPY --from=builder /opt/app/<path-to-target>/my-1.0.0.jar .
    EXPOSE 8080
    CMD [ "java", "-jar", "/opt/app/my-1.0.0.jar" ]