11

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?

vlio20
  • 8,955
  • 18
  • 95
  • 180
  • Can you tell why you are copying the pom files into the docker image instal of the final jar ? Or do you really want to build insider the docker container the resulting jar ? – khmarbaise Aug 03 '18 at 20:24
  • Sure, the pom.xml of the sub-module is the child of the parent pom. So I need it when I am building the sub-module in the Docker container – vlio20 Aug 04 '18 at 09:22
  • 1
    I would suggest to run the Maven outside the docker container and copy only the resulting jar into the docker container cause based on that your container contains much things you don't need. – khmarbaise Aug 04 '18 at 12:48
  • It's an old post, but. Agreed with @khmarbaise. You are building a giant docker image. Run maven build outside, or use multi stage docker build. – Claudio Weiler Aug 17 '21 at 16:13
  • similar to: https://stackoverflow.com/q/68808252/400544 – pgpb.padilla Aug 17 '21 at 16:24

1 Answers1

23

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" ]
Sebastian
  • 4,770
  • 4
  • 42
  • 43
  • Where do we have to put this Dockerfile? – Will Wost Mar 29 '21 at 20:35
  • that's up to you. Some people put dockerfiles in the project root directory, while others uses another repo for image creation. – Sebastian Mar 29 '21 at 23:25
  • 1
    What I wanted to say is that do we need to create a Dockerfile for every sub-module or only one in the project root directory? – Will Wost Mar 29 '21 at 23:35
  • 1
    just one dockerfile – Sebastian Mar 31 '21 at 17:09
  • Sorry if this is a newb question, but why would we use -DexcludeArtifactIds? Is that to prevent some sort of circular reference if module1 depends on module2, and module2 depends on module1? – fudge Apr 14 '23 at 13:36
  • 1
    @fudge sry I can't remember this one. But I think it was to avoid having duplicate runtime deps. Duplicated deps is a tricky issue to spot, only happens on runtime and the load order may vary. – Sebastian Apr 14 '23 at 14:43