GoogleContainerTools / GoogleContainerTools/jib

Exec user process caused: no such file or directory when using custom JRE and distroless base image

Open
#3,829 5 comments 0 reactions 0 assignees View on GitHub
area/jib-gradle-plugin priority:p3 type:bug
Dominant language
Java
Stars
14.5k
Forks
1.5k
PR merge metrics
No merged PRs in 30d

Description

Hello everyone, here I came scratching my head with this current issue related to Jib (I presume).

**Environment**:

- *Jib version:* 3.3.0
- *Build tool:* Gradle 7.5
- *OS:* Linux

**Description of the issue**:

This is a strange behavior that might or might not be connected actually to the Jib plugin, but I am left without any more other things to try on my own to be honest.

As can be seen from the plugin configuration, the working directory contains another directory called 'minimal-jre' which is produced by another bash script prior to having the Jib gradle plugin actually being ran.

The bash script simply runs jdeps over the source code and uses jlink with that output to create a custom JRE and place it in the 'minimal-jre' folder:

``` #Run jlink to create the custom runtime.
jlink --strip-debug \
--no-header-files \
--no-man-pages \
--compress=2 \
--add-modules $(cat jre-deps.info) \
--output $TARGET_FOLDER
```

The extraDirectories is supposed to copy the contents from inside that folder into the container at the path '/minimal-jre' so ideally I would have my JRE present in the container at that part:

```
extraDirectories {
paths {
path {
from = file('minimal-jre') // Folder which contains the custom JRE.
into = '/minimal-jre'
}
}
permissions = ['/minimal-jre/bin/java': '755']
}
```

We are pulling the gcr.io/distroless/java-base-debian11 with a specific SHA256 to get a base image which contains everything necessary to run the JVM, without a JDK/JRE in itself:

```
image = 'gcr.io/distroless/java-base-debian11@sha256:b20ec5e5d7ba95a030e800dd45e2d01df60ef01bf7c99c7c33d367c89a2a4b24'
```

On top of that image, we should have the 'minimal-jre' folder inserted by extraDirectories, so theoretically we have a distroless image now with a custom JRE inside, and that is where we customize the entrypoint to point to the correct java binary:

```
['/minimal-jre/bin/java', '-cp', '@/app/jib-classpath-file', '@/app/jib-main-class-file', "$JAVA_OPTS".toString()]
```

**Expected behavior**:

When running the container image created by Jib, it should be up and running, however, when deploying to a local Rancher k8s distribution (with containerd as runtime, nerdctl as binary) the following error shows up:

```
exec /minimal-jre/bin/java: no such file or directory
```

When running the container image created by Jib inside an Azure Kubernetes cluster, the following error shows up:
```
standard_init_linux.go:228: exec user process caused: no such file or directory
```

Clearly, there is something wrong with the entrypoint, or the extraDirectories not working as I supposed they are working, as both deployment clusters seem to believe that the '/minimal-jre/bin/java' does not exist or are unable to find them.

However, extraDirectories does validate the input path when evaluated, so if the 'minimal-jre' didn't exist before the Jib plugin ran, you'd encounter a build error. No build error means that it's able to parse the local folder and put it in the container.

Next thing I looked into was creating a tarball out of the image and looking into it's blobs, it is clear that the folder is actually present: (?!)

![image](https://user-images.githubusercontent.com/26601265/198296696-3571aec0-9934-43d7-be17-cb7d9b87eb14.png)

Why would the runtime then complain regarding this? Have I missed something? The base image should contain all the binaries required for the JVM, but the error clearly seems to be related to the entrypoint and the java binary not being found.

**Steps to reproduce**:

1. Just create a minimalist Spring Boot application that prints hello world (can copy any project).
2. Run jdeps over the fat jar produced by Spring Boot and run the jlink command from above
3. Use same jib configuration and check if the image is running

**`jib-gradle-plugin` Configuration**:
```groovy
jib {
extraDirectories {
paths {
path {
from = file('minimal-jre') // Folder which contains the custom JRE.
into = '/minimal-jre'
}
}
permissions = ['/minimal-jre/bin/java': '755']
}
from {

image = 'gcr.io/distroless/java-base-debian11@sha256:b20ec5e5d7ba95a030e800dd45e2d01df60ef01bf7c99c7c33d367c89a2a4b24'

}
to {
image = "$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA"

}
container {
ports = ['8080']
format = 'OCI'
entrypoint = ['/minimal-jre/bin/java', '-cp', '@/app/jib-classpath-file', '@/app/jib-main-class-file', "$JAVA_OPTS".toString()]
}
pluginExtensions {
pluginExtension {
implementation = 'com.google.cloud.tools.jib.gradle.extension.springboot.JibSpringBootExtension'
}
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.