ClassNotFoundException when starting spring boot application from distroless container

Viewed 277

I am facing a ClassNotFoundException when I try to run my docker image - I just don't understand why this is happening.

When running with docker run --rm -i spring-boot-config-demo:dev this results into

Exception in thread "main" java.lang.ClassNotFoundException: com.example.DemoApplication
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:398)
        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.JarLauncher.main(JarLauncher.java:88)

However I am able to run it with gradlew.bat bootRun and even with java -jar .\build\libs\app.jar without any issues.

Even when I unzip the jar and have a look at at MANIFEST.MF it seems right. Any idea???

Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.DemoApplication
Spring-Boot-Version: 2.4.4
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx

This is what my settings.gradle looks like

// Required so that gradle knows where to pull plugins from
pluginManagement {
    repositories {
        maven {
            url 'https://artifact.foobar.com/internal'
        }
    }
}

rootProject.name = 'demo'

And my build.gradle file

plugins {
    // https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/
    id 'org.springframework.boot' version '2.4.4'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE
    id 'java'
}

springBoot {
    // https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#packaging-executable-configuring-main-class
    mainClassName = 'com.example.DemoApplication'
}

bootJar {
    archiveFileName = 'app.jar'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    maven {
        url 'https://artifact.foobar.com/internal'
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'

    implementation 'com.azure:azure-data-appconfiguration:1.1.11'
    implementation 'com.microsoft.azure:spring-cloud-azure-appconfiguration-config-web:1.3.0'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

test {
    useJUnitPlatform()
}

And here is my Dockerfile

# Stage 1 - Build the application
FROM docker.artifact.foobar.com/gradle:7.0.0-jdk11 as build
    
# Change working directory
WORKDIR /app

# Copy files to gradle image
COPY ./src .
COPY ./build.gradle .
COPY ./settings.gradle .

# Build
RUN gradle bootJar -x test --no-watch-fs

# Stage 2 - Run the application
FROM gcr.io/distroless/java:11 as run
WORKDIR /app
COPY --from=build /app/build/libs/app.jar /app/app.jar

CMD ["app.jar"]

And folder structure, where DemoApplication.java contains my public static void main(String[])

│   .gitignore
│   build.gradle
│   Dockerfile
│   gradlew
│   gradlew.bat
│   README.md
│   settings.gradle
├───.gradle
│ [...]
├───build
│ [...]
├───gradle
│   └───wrapper
│           gradle-wrapper.jar
│           gradle-wrapper.properties
└───src
    ├───main
    │   ├───java
    │   │   └───com
    │   │       └───example
    │   │               DemoApplication.java
    │   │               HelloController.java
    │   │               MessageProperties.java
    │   │
    │   └───resources
    │           application.yml
    │           bootstrap.properties
    │
    └───test
        └───java
            └───com
                └───example
                        DemoApplicationTests.java

Content of DemoApplication.java

package com.example;

// ... 

@SpringBootApplication
@EnableConfigurationProperties(MessageProperties.class)
public class DemoApplication {
    // ...

    public static void main(String[] args) {
        // ... 
    }
}
0 Answers
Related