quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.56k stars 2.62k forks source link

Native build always requires docker/podman, even with quarkus.native.container-build=false and native-image in JAVA_HOME #36207

Closed marcio-absmartly closed 9 months ago

marcio-absmartly commented 11 months ago

Describe the bug

It seems that with Quarkus 3.4 a native build will always require Docker/podman, even with quarkus.native.container-build=false and native-image in JAVA_HOME This was not the case in 3.0.4.

Expected behavior

Docker/podman is not required when quarkus.native.container-build=false and native-image in JAVA_HOME. I think requiring Docker-in-Docker is unnecessary.

Actual behavior

75.24       > io.quarkus.builder.BuildException: Build failure: Build failed due to errors
75.24           [error]: Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#resolveNativeImageBuildRunner threw an exception: java.lang.IllegalStateException: No container runtime was found. Make sure you have either Docker or Podman installed in your environment.

How to Reproduce?

No response

Output of uname -a or ver

Linux marcio-xps 6.2.0-1012-lowlatency #12-Ubuntu SMP PREEMPT_DYNAMIC Thu Aug 17 16:45:08 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "17.0.7" 2023-04-18 OpenJDK Runtime Environment Temurin-17.0.7+7 (build 17.0.7+7) OpenJDK 64-Bit Server VM Temurin-17.0.7+7 (build 17.0.7+7, mixed mode, sharing)

GraalVM version (if different from Java)

22.3.3

Quarkus version or git rev

3.4.1.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Gradle 8.3

Additional information

No response

geoand commented 11 months ago

cc @zakkak

zakkak commented 11 months ago

@marcio-absmartly are you sure JAVA_HOME is pointing to a GraalVM / Mandrel distribution? The java -version seems to contradict it.

Can you please run $JAVA_HOME/native-image --version in the same terminal you are performing the build and post the output?

Thanks

marcio-absmartly commented 10 months ago

Hi @zakkak

Thanks for your patience. I may have pasted the version from my own terminal, but my build is running in a docker container which builds fine with 3.0.4.Final but fails with the above error when changing Quarkus version to 3.2.x.

Following are some more details.

The Dockerfile is custom built from gradle:8.3.0-jdk17 and native image is installed via:

curl -Lso mandrel.tar.gz https://github.com/graalvm/mandrel/releases/download/mandrel-23.0.1.2-Final/mandrel-java17-linux-amd64-23.0.1.2-Final.tar.gz \
tar --strip-components=1 -xf mandrel.tar.gz

From inside the container:

local@/home/gradle/native-image/bin# ./native-image  --version
native-image 17.0.8 2023-07-18
OpenJDK Runtime Environment Mandrel-23.0.1.2-Final (build 17.0.8+7)
OpenJDK 64-Bit Server VM Mandrel-23.0.1.2-Final (build 17.0.8+7, mixed mode)
local@/home/gradle/native-image/bin# ./java -version
openjdk version "17.0.8" 2023-07-18
OpenJDK Runtime Environment Temurin-17.0.8+7 (build 17.0.8+7)
OpenJDK 64-Bit Server VM Temurin-17.0.8+7 (build 17.0.8+7, mixed mode, sharing)
local@/home/gradle/native-image/bin# env | grep _HOME
JAVA_HOME=/home/gradle/native-image
GRAALVM_HOME=/home/gradle/native-image
GRADLE_HOME=/opt/gradle
local@/home/gradle/native-image/bin# uname -a
Linux d08da4455b3f 6.2.0-1015-lowlatency #15-Ubuntu SMP PREEMPT_DYNAMIC Fri Oct  6 10:04:59 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
gsmet commented 10 months ago

Do you have the full stracktrace? I would be interesting to see what requires Docker.

marcio-absmartly commented 10 months ago

Here you go:

155.8 > There was a failure while executing work items
155.8    > A failure occurred while executing io.quarkus.gradle.tasks.worker.BuildWorker
155.8       > io.quarkus.builder.BuildException: Build failure: Build failed due to errors
155.8           [error]: Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#resolveNativeImageBuildRunner threw an exception: java.lang.IllegalStateException: No container runtime was found. Make sure you have either Docker or Podman installed in your environment.
155.8           at io.quarkus.runtime.util.ContainerRuntimeUtil.detectContainerRuntime(ContainerRuntimeUtil.java:53)
155.8           at io.quarkus.runtime.util.ContainerRuntimeUtil.detectContainerRuntime(ContainerRuntimeUtil.java:39)
155.8           at io.quarkus.deployment.pkg.steps.NativeImageBuildContainerRunner.<init>(NativeImageBuildContainerRunner.java:31)
155.8           at io.quarkus.deployment.pkg.steps.NativeImageBuildLocalContainerRunner.<init>(NativeImageBuildLocalContainerRunner.java:19)
155.8           at io.quarkus.deployment.pkg.steps.NativeImageBuildStep.resolveNativeImageBuildRunner(NativeImageBuildStep.java:352)
155.8           at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
155.8           at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
155.8           at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
155.8           at java.base/java.lang.reflect.Method.invoke(Method.java:568)
155.8           at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:864)
155.8           at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
155.8           at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
155.8           at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
155.8           at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
155.8           at java.base/java.lang.Thread.run(Thread.java:833)
155.8           at org.jboss.threads.JBossThread.run(JBossThread.java:501)
zakkak commented 10 months ago

@marcio-absmartly if you are not getting a message like the following:

Cannot find the `native-image` in the GRAALVM_HOME, JAVA_HOME and System PATH. Install it using `gu install native-image` Attempting to fall back to container build.

Then quarkus.native.container-build is probably set to true.

For builds using a local Mandrel/GraalVM installation you should set it to false (e.g. -Dquarkus.native.container-build=false)

marcio-absmartly commented 10 months ago

No, I am not getting that error message, and this the command I run inside the container:

gradle build -Dquarkus.package.type=native -Dquarkus.native.container-build=false

Like I said, the only change for it to stop working, is to bump version from 3.0.4.Final to 3.2.7.Final

zakkak commented 10 months ago

The stack trace indicates that you are reaching this line https://github.com/quarkusio/quarkus/blob/f8666248bc0ace2e85c894e68a3750b267050e7b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java#L352

The fact that you are not getting the error message I mention above indicates that the code didn't enter the if statement in https://github.com/quarkusio/quarkus/blob/f8666248bc0ace2e85c894e68a3750b267050e7b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java#L335-L348

Which in theory should only happen if any of the following holds:

  1. quarkus.native.container-build is true
  2. quarkus.native.container-runtime is set
  3. quarkus.native.remote-container-build is true

However, the same checks are performed in 3.0.4.Final and you say that the same configuration works there, so there is something else going on.

Could you share a reproducer?

marcio-absmartly commented 10 months ago

I don't have time to prepare one in the next few days, but will get to it then. However, it should happen with a simple Quarkus build using my settings which I will consolidate below, in case this already gives a clue:

application.properties

quarkus.banner.enabled=false
quarkus.package.type=fast-jar
quarkus.native.container-build=true
quarkus.native.additional-build-args=-march=haswell
quarkus.native.resources.includes=*.json
quarkus.smallrye-health.ui.enable=false
quarkus.http.port=8087
quarkus.http.access-log.enabled=true
quarkus.http.access-log.exclude-pattern=^/q/(health|metrics).*

Dockerfile (simplified)

# syntax = docker/dockerfile:experimental
ARG BUILD_ROOT=/home/gradle
ARG BUILD_NAME={{ name }}

FROM gradle:8.3.0-jdk17 as BUILDER

ARG BUILD_ROOT
ARG BUILD_NAME

# install native image
WORKDIR $BUILD_ROOT/native-image

RUN apt update \
    && apt install -y g++ zlib1g-dev libfreetype6-dev \
    && curl -Lso mandrel.tar.gz https://github.com/graalvm/mandrel/releases/download/mandrel-23.0.1.2-Final/mandrel-java17-linux-amd64-23.0.1.2-Final.tar.gz \
    && tar --strip-components=1 -xf mandrel.tar.gz

# copy root gradle
WORKDIR $BUILD_ROOT/src
COPY --chown=gradle:gradle build.gradle settings.gradle gradle.properties .
COPY --chown=gradle:gradle gradle gradle

# copy lib and run tests
WORKDIR $BUILD_ROOT/src/lib
COPY --chown=gradle:gradle lib .
RUN --mount=type=cache,sharing=private,id=gradle,target=/root/.gradle \
    SPOTBUGS=0 SPOTLESS=0 \
    gradle -q --no-daemon clean

# copy test and build native image
WORKDIR $BUILD_ROOT/src/$BUILD_NAME
COPY --chown=gradle:gradle $BUILD_NAME .
RUN --mount=type=cache,sharing=private,id=gradle,target=/root/.gradle \
    JAVA_HOME=$BUILD_ROOT/native-image \
    GRAALVM_HOME=$BUILD_ROOT/native-image \
    PATH="$JAVA_HOME/bin:$PATH" \
    gradle -q --no-daemon clean build -Dquarkus.package.type=native -Dquarkus.native.container-build=false

# never reaches this part

build.gradle

plugins {
    id "application"
    id "io.quarkus"
}

quarkusDev {
    workingDir = project.projectDir
}

dependencies {
    implementation enforcedPlatform("io.quarkus.platform:quarkus-bom:${quarkusVersion}")
    implementation 'io.quarkus:quarkus-vertx'
    implementation 'io.quarkus:quarkus-arc'
    implementation 'io.quarkus:quarkus-resteasy-reactive-jackson'
    implementation 'io.quarkus:quarkus-smallrye-health'
    implementation 'io.quarkus:quarkus-micrometer-registry-prometheus'
    implementation group: 'io.quarkiverse.jdbc', name: 'quarkus-jdbc-clickhouse', version: '3.0.1'

    testImplementation 'io.quarkus:quarkus-junit5'
}

compileJava{
    dependsOn compileQuarkusGeneratedSourcesJava
}

compileTestJava{
    dependsOn compileQuarkusTestGeneratedSourcesJava
}

spotlessJava{
    dependsOn compileQuarkusGeneratedSourcesJava, compileQuarkusTestGeneratedSourcesJava
}
zakkak commented 10 months ago

The only thing I can think of is that for some reason -Dquarkus.package.type=native -Dquarkus.native.container-build=false do not override the corresponding settings in the application.properties.

geoand commented 9 months ago

Closing for lack of a reproducer.

If one does become available, we can reopen the issue