oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.4k stars 1.64k forks source link

[GR-52221] Allow native-image-plugin to use a docker image as executable #8342

Open cmuramoto opened 9 months ago

cmuramoto commented 9 months ago

Problem:

In order to work, the maven-plugin

    <groupId>org.graalvm.nativeimage</groupId>
    <artifactId>native-image-maven-plugin</artifactId>
    <version>21.2.0</version>

requires a local installation of graalvm with native-image command on PATH.

There are some OS related issues, e.g. #5814, that prevent building static images, which may disrupt CI/CD workflows.

Solution:

Instead of relying on a local native-image executable one could launch a docker image based on an OS that does not suffer from linking issues.

Example:

FROM ubuntu:20.04

RUN apt update \
    && apt install -y wget gcc zlib1g-dev \
    && wget https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz \
    && tar -xzf graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz \
    && rm -f graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz \
    && mv graalvm-community-openjdk-21.0.2+13.1/ opt/java

ENV PATH="${PATH}:/opt/java/bin"

ENTRYPOINT ["native-image"] 

Can be used as a replacement for a local executable.

docker container run --workdir $PWD/target -v $HOME:$HOME --rm my.company/native-image-builder:latest -cp ... --static -H:Class=my.Main 

This could be hooked into native-image-maven-plugin, e.g., by specifying a dockerImage attribute.

<plugin>
    <groupId>org.graalvm.nativeimage</groupId>
    <artifactId>native-image-maven-plugin</artifactId>
    <configuration>
        <dockerImage>my.company/native-image-builder:latest</dockerImage>
        <buildArgs>
            <buildArg>...</buildArg>
            <buildArg>--static</buildArg>
        </buildArgs>
        <mainClass>${native.image.entrypoint}</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>native-image</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
</plugin>

Once specified, the NativeImageMojo has just to set up the ProcessBuilder with --workdir based on

@Parameter(defaultValue = "${project.build.directory}", property = "outputDir", required = true)
private File outputDirectory;

Finally, the necessary volumes for the classpath can be deduced in the mojo from ArtifactRepository (for .m2/repository) and the project build directory itself.

fernando-valdez commented 9 months ago

Thanks for creating this feature request. I will evaluate your feature request and will let you know if I have any questions.

fernando-valdez commented 9 months ago

Internal ticket created: GR-52221