简体   繁体   中英

docker with maven jar

I'm running a maven project in a docker container, I'm getting Could not find or load main class error.

FROM maven:3.6.0-jdk-11-slim AS build

COPY src src
COPY pom.xml .
RUN mvn -f pom.xml clean package install

FROM openjdk:8-jre

COPY --from=build /target /opt/target
WORKDIR /target

RUN ls

CMD ["java", "-jar", "Customer.jar"]

above assembly was created with following plugin in <build>

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>com.companyname.Customer</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id> <!-- this is used for inheritance merges -->
            <phase>package</phase> <!-- bind to the packaging phase -->
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Error

Error: Could not find or load main class com.mycompany.Customer

Question: How do you set class path to a jar file in docker?


Edit

I tested with the following but same issue.

CMD ["java", "-cp", "Customer.jar:libs/*", "com.company.customers.Customer"]

Error: Could not find or load main class com.company.customers.Customer

It's not a Docker issue it's a Java issue. There are several ways to define classpath entries to run an executable jar.

Shaded or Uber jar approach

In this case you sould create a shaded jar which contains all dependent classes in one executable jar file. Maven has a plugin called Apache Maven Shade Plugin to create that uber-jar artifact.

Finally just run:

java -jar shaded-artifact.jar

or in Docker

CMD ["java", "-jar", "shaded-artifact.jar"]

Command line classpath approach

If the created jar artifact requires the existence of other (dependent) jars you have to specify the classpath. In this case copy all required jars into a folder eg lib and use the following command:

java -cp '<name-of-jar.jar>:<path-of-dependencies>' <fully.quialified.main.ClassName>

As you can see either wildcard (*) character and multiple classpath element is allowed separated by : so

java -cp 'Customer.jar:libs/*' com.mycompany.Customer

in Docker

CMD ["java", "-cp", "Customer.jar:libs/*", "com.mycompany.Customer"]

Classpath in MANIFEST approach

After you collecteded all those dependent artifact into a folder then you just add a Class-Path entry into your META-INF/MANIFEST.MF file like this:

Class-Path: . lib/*

and run

java -jar Customer.jar

or in Docker

CMD ["java", "-jar", "Customer.jar"]

Which of those is the best depends on so many things, you have to choose.

Edit:

Based on updated question it seems the uber jar was created by assembly plugin using jar-with-dependencies predefined descriptor. This will create another jar file which placed under target (output) folder and its name ends with -jar-with-dependencies.jar

  1. Use that jar insead of basic artifact.
  2. Do a double check to make sure all of <mainClass> entries point to an existing class. You've mentioned three different main class in the same question.
    • com.companyname.Customer

    • com.mycompany.Customer

    • com.company.customers.Customer

  3. Pay attention for both of Linux and Java are case sensitive. On this basis the class name must be Customer exactly and all folder names must be lowercase.

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM