1

I have a problem that my main class cannot be loaded when running mvn package from docker (at the same time it works perfectly when doing mvn package from Eclipse), Related problem with it is that I cannot figure out where actually Docker saves .jar file. I know where Eclipse stores it, but where docker stores it I don't understand. I wrote simple app in Eclipse and defined my pom.xml so I can build fat .jar (with all dependant compiled .jars inside it). In that I call Maven by myself (manually in Eclipse doing mvn package, which is what I want to avoid - I would like to Docker do the Maven stuff instead of me). And everything works fine this way when I do it manually. Now, my Dockerfile was like this at that point:

FROM openjdk:8-jdk-alpine
EXPOSE 4567  
ADD target/ReadDocFile.jar /opt/demo/ReadDocFile.jar
CMD ["java","-jar","/opt/demo/ReadDocFile.jar"]

As you can see, I'm copying from my target folder (where I manually stored my fat .jar using Eclipse) to some path inside docker container and call it. And everything works well if calling .jar file from local project like that.

Now, I don't want to call mvn package by myself but I want to Docker do it for me. So I wrote:

ADD src /code/src
RUN ["mvn", "package"]

EXPOSE 4567  
ADD target/ReadDocFile.jar /opt/demo/ReadDocFile.jar
CMD ["java","-jar","/opt/demo/ReadDocFile.jar"]

But after I call that same pom.xml that is working with mvn package inside Eclipse (and this time via Dockerfile as you can see with mvn package in RUN part in the upper code), compilation fails:

Error: Could not find or load main class com.dario.apachepoi.PrintSomething

Why is that? It's the same pom.xml. I can't understand why on the same pom.xml compilation won't work? Seems to me it's looking on local folder (target) but shouldn't it look somewhere inside docker layer for .jar file (where?) ?

My full Dockerfile looks like this:

FROM maven:3.3-jdk-8-alpine

WORKDIR /code

# Prepare by downloading dependencies
ADD pom.xml /code/pom.xml
RUN ["mvn", "dependency:resolve"]  
RUN ["mvn", "verify"]

# Adding source, compile and package into a fat jar
ADD src /code/src
RUN ["mvn", "package"]

EXPOSE 4567  
#ADD target/ReadDocFile.jar /opt/demo/ReadDocFile.jar
CMD ["java","-jar","target/ReadDocFile.jar"]

Also, that path target/ReadDocFile.jar bothers me a lot - it's looking on my local store. Shouldn't be looking inside docker container? It that is the case, how can I figure out what is the path where maven running in docker stores my jar?

My pom.xml file (compiled well manually with mvn package inside Eclipse, but not compiled well when running mvn package inside docker):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.dario.apachepoi</groupId>
  <artifactId>apachepoi</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
   <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.15</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-examples -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-examples</artifactId>
        <version>3.15</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-excelant -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-excelant</artifactId>
        <version>3.15</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.15</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>3.15</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-scratchpad</artifactId>
        <version>3.15</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans -->
    <dependency>
        <groupId>org.apache.xmlbeans</groupId>
        <artifactId>xmlbeans</artifactId>
        <version>2.6.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.github.virtuald/curvesapi -->
    <dependency>
        <groupId>com.github.virtuald</groupId>
        <artifactId>curvesapi</artifactId>
        <version>1.04</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.0</version>
    </dependency>

  </dependencies>


    <build>
        <finalName>ReadDocFile</finalName>
        <plugins>

            <!-- download source code in Eclipse, best practice -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.10</version>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>false</downloadJavadocs>
                </configuration>
            </plugin>

            <!-- Set a compiler level -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                </configuration>
            </plugin>

        <!-- Maven Shade Plugin -->
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-shade-plugin</artifactId>
          <version>2.4.3</version>
          <executions>
             <!-- Run shade goal on package phase -->
            <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <!-- add Main-Class to manifest file -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>com.dario.apachepoi.PrintSomething</mainClass>
                </transformer>
              </transformers>
            </configuration>
              </execution>
          </executions>
        </plugin>

        </plugins>

    </build>

</project>

Please help!

Edit: I think something else must be written instead of my target folder? But what, what docker path to .jar generated inside docker?

DarioBB
  • 663
  • 2
  • 8
  • 29
  • How can this be duplicate? In that example maven instruction is passed on docker run – DarioBB Jan 05 '17 at 19:09
  • The answer to the other question provides an example of how to create a container using Maven. Like you it uses the offical Maven image, but utilizes the very handy "onbuild" image that leverages the very useful ONBUILD instruction. BTW the "install" goal in Maven will automatically include the "package" goal so results in the same desired result – Mark O'Connor Jan 05 '17 at 19:21
  • Thank you. I will try it. Does it mean I must run docker with: docker run... and mvn (as you wrote it)? Because here I have inside Dockerfile my mvn instruction – DarioBB Jan 05 '17 at 19:26
  • 1
    "docker build" will build a container image. The ONBUILD instructions provided by the base image will ensure that "mvn install" is invoked. That is the purpose of ONBUILD to define your technology specific build instructions. Very very useful and you'll see this technique duplicated in all the official images: ruby, golang, etc – Mark O'Connor Jan 05 '17 at 19:30

0 Answers0