diff --git a/docker-plugin/src/main/java/io/micronaut/gradle/docker/NativeImageDockerfile.java b/docker-plugin/src/main/java/io/micronaut/gradle/docker/NativeImageDockerfile.java index 541bd4bf..68fe760f 100644 --- a/docker-plugin/src/main/java/io/micronaut/gradle/docker/NativeImageDockerfile.java +++ b/docker-plugin/src/main/java/io/micronaut/gradle/docker/NativeImageDockerfile.java @@ -65,6 +65,11 @@ public abstract class NativeImageDockerfile extends Dockerfile implements Docker private static final String ARM_ARCH = "aarch64"; private static final String X86_64_ARCH = "x64"; + private static final String GRAALVM_DOWNLOAD_BASE_URL = "https://download.oracle.com/graalvm"; + private static final String GRAALVM_DISTRIBUTION_PATH = "/%s/%s/graalvm-jdk-%s_linux-%s_bin.tar.gz"; + //Latest version of GraalVM for JDK 17 available under the GraalVM Free Terms and Conditions (GFTC) licence + private static final String GRAALVM_FOR_JDK17 = "17.0.12"; + /** * @return The JDK version to use with native image. Defaults to the toolchain version, or the current Java version. */ @@ -132,6 +137,17 @@ public abstract class NativeImageDockerfile extends Dockerfile implements Docker @Optional public abstract Property getGraalReleasesUrl(); + /** + * Return the full URL of the GraalVM distribution to use. By default, it + * uses the base URL from {@link #getGraalReleasesUrl()} and searches in a + * location known to exist when the plugin was built. + * + * @return the URL of the GraalVM distribution to use + */ + @Input + @Optional + public abstract Property getGraalVMDistributionUrl(); + @Input @Override public abstract Property getTargetWorkingDirectory(); @@ -188,6 +204,17 @@ public NativeImageDockerfile() { getTargetWorkingDirectory().convention(DEFAULT_WORKING_DIR); getExposedPorts().convention(Collections.singletonList(8080)); getGraalImage().convention(getJdkVersion().map(NativeImageDockerfile::toGraalVMBaseImageName)); + getGraalReleasesUrl().convention(GRAALVM_DOWNLOAD_BASE_URL); + var distributionPath = getJdkVersion().zip(getGraalArch(), (jdk, arch) -> { + if ("17".equals(jdk)) { + getLogger().warn("You are using the latest release of GraalVM available under the GraalVM Free Terms and Conditions (GFTC) licence (" + GRAALVM_FOR_JDK17 + "). Consider upgrading to Java 21."); + return GRAALVM_DISTRIBUTION_PATH.formatted(jdk, "archive", GRAALVM_FOR_JDK17, arch); + } + return GRAALVM_DISTRIBUTION_PATH.formatted(jdk, "latest", jdk, arch); + }); + getGraalVMDistributionUrl().convention( + getGraalReleasesUrl().zip(distributionPath, (base, path) -> base + path) + ); getNativeImageOptions().convention(project .getTasks() .named(NativeImagePlugin.NATIVE_COMPILE_TASK_NAME, BuildNativeImageTask.class) @@ -436,8 +463,8 @@ private void setupInstructions(List additionalInstructions) { String graalArch = getGraalArch().get(); // https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_linux-aarch64_bin.tar.gz String fileName = "graalvm-jdk-" + jdkVersion + "_linux-" + graalArch + "_bin.tar.gz"; - String releasesUrl = getGraalReleasesUrl().getOrElse("https://download.oracle.com/graalvm"); - runCommand("curl -4 -L " + releasesUrl + "/" + jdkVersion + "/latest/" + fileName + " -o /tmp/" + fileName); + String graalvmDistributionUrl = getGraalVMDistributionUrl().get(); + runCommand("curl -4 -L " + graalvmDistributionUrl + " -o /tmp/" + fileName); runCommand("tar -zxf /tmp/" + fileName + " -C /tmp && ls -d /tmp/graalvm-jdk-"+ jdkVersion + "* | grep -v \"tar.gz\" | xargs -I_ mv _ /usr/lib/graalvm"); runCommand("rm -rf /tmp/*"); if (toMajorVersion(jdkVersion) < 21) { diff --git a/functional-tests/src/test/groovy/io/micronaut/gradle/docker/DockerNativeFunctionalTest.groovy b/functional-tests/src/test/groovy/io/micronaut/gradle/docker/DockerNativeFunctionalTest.groovy index d2138b4f..6568ab9f 100644 --- a/functional-tests/src/test/groovy/io/micronaut/gradle/docker/DockerNativeFunctionalTest.groovy +++ b/functional-tests/src/test/groovy/io/micronaut/gradle/docker/DockerNativeFunctionalTest.groovy @@ -17,7 +17,7 @@ class DockerNativeFunctionalTest extends AbstractEagerConfiguringFunctionalTest @Lazy String defaultDockerFrom = "FROM $defaultBaseImage" - def "test build docker native image for runtime #runtime"() { + def "test build docker native image for runtime #runtime (JDK #jdk)"() { given: settingsFile << "rootProject.name = 'hello-world'" println settingsFile.text @@ -45,6 +45,7 @@ class DockerNativeFunctionalTest extends AbstractEagerConfiguringFunctionalTest dockerfileNative { args('-Xmx64m') instruction \"\"\"HEALTHCHECK CMD curl -s localhost:8090/health | grep '"status":"UP"'\"\"\" + jdkVersion = "$jdk" } graalvmNative.binaries.all { @@ -101,10 +102,11 @@ micronaut: task.outcome == TaskOutcome.SUCCESS where: - runtime | nativeImage - "netty" | "FROM ghcr.io/graalvm/native-image-community:17-ol${DefaultVersions.ORACLELINUX}" - "lambda_provided" | 'FROM amazonlinux:2023 AS graalvm' - "jetty" | "FROM ghcr.io/graalvm/native-image-community:17-ol${DefaultVersions.ORACLELINUX}" + runtime | jdk | nativeImage + "netty" | 17 | "FROM ghcr.io/graalvm/native-image-community:17-ol${DefaultVersions.ORACLELINUX}" + "lambda_provided" | 17 | 'FROM amazonlinux:2023 AS graalvm' + "lambda_provided" | 21 | 'FROM amazonlinux:2023 AS graalvm' + "jetty" | 17 | "FROM ghcr.io/graalvm/native-image-community:17-ol${DefaultVersions.ORACLELINUX}" } void 'build mostly static native images when using distroless docker image for runtime=#runtime'() { @@ -649,7 +651,7 @@ micronaut: build "dockerfileNative" def dockerFile = normalizeLineEndings(file("build/docker/native-main/DockerfileNative").text) dockerFile = dockerFile.replaceAll("[0-9]\\.[0-9]+\\.[0-9]+", "4.0.0") - .trim() + .trim() then: dockerFile == """