java-how to solve Error: Could not find or load main class error when using docker with springboot.
Problem
When we use docker with spring boot projects, sometimes, we get this error:
➜ bin git:(main) ✗ ./docker-run.sh myharbor.com/bswen/spring
Error: Could not find or load main class com.bswen.app7.Main
The core exception is:
Error: Could not find or load main class com.bswen.app7.Main
Environment
- java 1.8
- Spring Boot 2.3
- Intellij IDEA
- Docker 19
Debug
The Dockerfile:
FROM openjdk:8-jdk-alpine
MAINTAINER [email protected]
ENV APPROOT="/opt/app7"
ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib ${APPROOT}/lib
COPY ${DEPENDENCY}/META-INF ${APPROOT}/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes ${APPROOT}
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-cp","/opt/app8:/opt/app7/lib/*","-Droot.dir=/opt/app7","com.bswen.app7.Main"]
EXPOSE 8082
The Main class of this spring boot application:
package com.bswen.app7;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class,args);
}
}
If we run the app with gradle directly like this:
./gradlew app7:bootRun
It works, and if we run the spring boot docker image directly without kubernetes like this:
docker run app7:latest
We get the error again:
Error: Could not find or load main class com.bswen.app7.Main
Reason
According to the above debug process, we can found that the real problem should be the Dockerfile, it caused the exception in docker environment.
Solution
We found that there is a wrong character in the Dockerfile, which cause the spring boot app starts with a wrong classpath, that’s the key problem, we changed the Dockerfile like this:
FROM openjdk:8-jdk-alpine
MAINTAINER [email protected]
ENV APPROOT="/opt/app7"
ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib ${APPROOT}/lib
COPY ${DEPENDENCY}/META-INF ${APPROOT}/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes ${APPROOT}
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-cp","/opt/app7:/opt/app7/lib/*","-Droot.dir=/opt/app7","com.bswen.app7.Main"]
EXPOSE 8082
Pay attention to the last command in the Dockerfile of this spring boot app:
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-cp","/opt/app7:/opt/app7/lib/*","-Droot.dir=/opt/app7","com.bswen.app7.Main"]
EXPOSE 8082
The wrong configuration is “java … -cp /opt/app8…”, the right configuration is “java … -cp /opt/app7..”, this app is installed in “/opt/app7”, not “/opt/app8”, that’s the key point.