【问题标题】:SpringBoot + Docker - ClassNotFoundExceptionSpringBoot + Docker - ClassNotFoundException
【发布时间】:2021-10-13 04:42:42
【问题描述】:

我正在尝试对现有的 maven SpringBoot 项目进行 Docker 化,但我无法让它在容器中启动应用程序。该应用程序在它之外完美运行(使用我的 IDE 和 java -jar target/app-1.0-SNAPSHOT.jar)所以我不确定问题是什么。

我的Dockerfile

# syntax=docker/dockerfile:1
FROM maven:3.6-jdk-11 AS build
WORKDIR /build
COPY src /src
COPY pom.xml .
RUN mvn clean package -DskipTests

FROM openjdk:11-jre-slim AS runtime    
WORKDIR /app
COPY --from=build /build/target .
CMD ["java" ,"-jar", "app-1.0-SNAPSHOT.jar"]

我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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.example</groupId>-->
    <artifactId>app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Backend</name>
    <description>Backend</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <start-class>com.example.Application</start-class>
        <log4jdbc.log4j2.version>1.16</log4jdbc.log4j2.version>
        <rest.assured.version>2.3.3</rest.assured.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
    </parent>

    <dependencies>
        <!--        Compile -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.5.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.5.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>5.4.5</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.4.4</version>
        </dependency>
        <!--        -->

        <!--        Runtime -->
        <dependency>
            <groupId>com.ibm.db2</groupId>
            <artifactId>jcc</artifactId>
            <version>11.5.5.0</version>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--        -->

        <!--        Optional -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--        -->

        <!--        Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.4.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <version>5.3.5.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>[3.2.2,)</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.6.2</version>
            <scope>test</scope>
        </dependency>
        <!--        -->

        <!--        Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.5.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.5.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>5.4.7</version>
        </dependency>
        <!--        -->

        <!--        Utilities -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>

        <!--        Java Table implementation-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>
        <!--        -->

        <!--        Package to convert words to sentence case -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.9</version>
        </dependency>
        <!--        -->

        <dependency>
            <groupId>net.sf.jt400</groupId>
            <artifactId>jt400</artifactId>
            <version>10.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.11</version>
        </dependency>

        <!--        Maths functions for player generation -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.6</version>
        </dependency>
        <!--        -->

        <!--        JSON Stuff -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.1</version>
        </dependency>
        <!--        -->

        <!--        Implementing and defining cmdline arguments -->
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.4</version>
        </dependency>
        <!--        -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M5</version>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.6</version>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.Application</mainClass>
                    <layout>ZIP</layout>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <reportSets>
                    <reportSet>
                        <reports>
                            <!-- select non-aggregate reports -->
                            <report>report</report>
                        </reports>
                    </reportSet>
                </reportSets>
            </plugin>
        </plugins>
    </reporting>
</project>

构建:

docker build -t app .

哪个成功了。

然后运行:

docker run --rm -it -p 8100:8100 app

抛出以下内容:

Exception in thread "main" java.lang.ClassNotFoundException: com.example.Application
    at java.base/java.net.URLClassLoader.findClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Unknown Source)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:46)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:467)

我也尝试了Apache Maven Shade Plugin,但对我没有帮助。

在我看来,Dockerfile 似乎没有任何问题,是否存在依赖关系问题?

我尝试将源文件复制到运行时阶段,但仍然没有成功。

【问题讨论】:

  • 你的应用程序/uber jar 中有com.example.Application 吗?
  • 你的清单文件有说明主类在哪里吗? com.example.Application 是默认值吗?另一种选择是让您的 Dockerfile 执行以下操作:CMD ["java" ,"-cp", "fully-qualified-classname-goes-here"]
  • @aksappy 是的
  • @jeremyt 我似乎没有清单文件?这很奇怪,因为没有它,应用程序也能完美运行。
  • @Inkblot 您可能会发现,当您在 Docker 之外运行它时,它可以工作,因为您只有一个主类(即只有一个 public static void main(String[] args) 方法),但我怀疑需要告诉 Docker 哪个你想用吗?

标签: java spring-boot docker maven


【解决方案1】:

复制src /src

我不是 Docker 专家,但我很惊讶构建并没有在那里失败。 src 在 / 上复制,但“mvn 包”在 /build 上运行。我不确定这是如何成功的,所以也许我错了,但我会尝试使用相对路径。

【讨论】:

  • 原来是问题所在!我将其更改为 COPY src src 并启动应用程序。我猜是构建成功让我失望了,谢谢你的帮助
  • 很好看。我用过的一个有用的工具是https://github.com/wagoodman/dive。能够确保不仅将您想要的文件复制到映像中,而且还值得检查您不想要的文件是否被错误复制,因为这会影响上传到 Docker Hub 的大小,并且下载到您的运行时环境,这可能会影响您的服务正常运行时间承诺。
猜你喜欢
  • 2021-11-19
  • 2019-09-05
  • 2021-04-05
  • 2021-06-02
  • 2021-07-17
  • 2018-09-04
  • 2019-08-04
  • 2021-03-02
  • 2019-10-02
相关资源
最近更新 更多