Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraalVMNativeImagePlugin produces broken docker images without native-image in the PATH #1492

Closed
pshirshov opened this issue Jan 28, 2022 · 9 comments · Fixed by #1500
Closed

Comments

@pshirshov
Copy link

Try to enable GraalVMNativeImagePlugin on a project and set

   graalVMNativeImageGraalVersion := Some("22.0.0.2"),

This would produce a broken docker image:

❯ docker run -ti --rm ghcr.io-graalvm-graalvm-ce-native-image:22.0.0.2
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "native-image": executable file not found in $PATH: unknown.
❯ docker run -ti --rm --entrypoint /bin/bash ghcr.io-graalvm-graalvm-ce-native-image:22.0.0.2
bash-4.4# native-image
bash: native-image: command not found
bash-4.4# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
bash-4.4# find / -name "native-image" -print
/opt/graalvm-ce-java17-22.0.0.2/bin/native-image
/opt/graalvm-ce-java17-22.0.0.2/lib/svm/bin/native-image
bash-4.4# exit
@pshirshov
Copy link
Author

And here is a quick monkeypatch:

    GraalVMNativeImage / UniversalPlugin.autoImport.containerBuildImage := Def.taskDyn {
      (Def.task {

        val baseImage     = s"ghcr.io/graalvm/graalvm-ce:ol8-${graalVMNativeImageGraalVersion.value.get}"
        val dockerCommand = (DockerPlugin.autoImport.dockerExecCommand in GraalVMNativeImage).value
        val streams       = Keys.streams.value

        val (baseName, tag) = baseImage.split(":", 2) match {
          case Array(n, t) => (n, t)
          case Array(n)    => (n, "latest")
        }

        val imageName = s"${baseName.replace('/', '-')}-native-image:$tag"
        import sys.process._
        if ((dockerCommand ++ Seq("image", "ls", imageName, "--quiet")).!!.trim.isEmpty) {
          streams.log.info(s"Generating new GraalVM native-image image based on $baseImage: $imageName")

          val dockerContent = Dockerfile(
            Cmd("FROM", baseImage),
            Cmd("WORKDIR", "/opt/graalvm"),
            ExecCmd("RUN", "gu", "install", "native-image"),
            ExecCmd("ENTRYPOINT", "native-image"),
            ExecCmd("RUN", "ln", "-s", s"/opt/graalvm-ce-${graalVMNativeImageGraalVersion.value.get}/bin/native-image", "/usr/local/bin/native-image"),
          ).makeContent

          val command = dockerCommand ++ Seq("build", "-t", imageName, "-")

          val pb: ProcessBuilder = sys.process.Process(command) #< new ByteArrayInputStream(dockerContent.getBytes())
          val ret = pb ! (DockerPlugin: { def publishLocalLogger(log: sbt.Logger): scala.AnyRef with scala.sys.process.ProcessLogger }).publishLocalLogger(streams.log)

          if (ret != 0)
            throw new RuntimeException("Nonzero exit value when generating GraalVM container build image: " + ret)

        } else
          streams.log.info(s"Using existing GraalVM native-image image: $imageName")

        Some(imageName)
      }: Def.Initialize[Task[Option[String]]])
    }.value,

@muuki88
Copy link
Contributor

muuki88 commented Jan 30, 2022

Thanks a lot @pshirshov

Could you explain what the issue is and open a PR? 😊👋

@pshirshov
Copy link
Author

and open a PR? blushwave

Yep

Could you explain what the issue

Well, in case the explanation I've added is not enough - probably I won't be able to explain better :(

@capacman
Copy link

capacman commented Feb 1, 2022

I think issue is related to graalvm image. With prior versions(prior to graalvm 22) gu install process creating a symbolic link(via alternatives i think) under /usr/bin but with version 22 it just install native-image binary under $JAVA_HOME/bin.

@capacman
Copy link

capacman commented Feb 1, 2022

I think it is as issue with all recently published graalvm images.i tried with 21.3.1 and failed again

@kgston
Copy link
Contributor

kgston commented Feb 2, 2022

Would be nice to get this fix in soon since there is no manual workaround it affects updated graalvm images on old versions too. My only concern is that it locks the OS type to ol8 in the monkeypatch. But I suppose it could be an additional option i.e. graalVMNativeImageGraalOSVersion.

@pshirshov
Copy link
Author

That's not the best possible solution, I guess it would be better to allow the user to override the native-image binary location

@kgston
Copy link
Contributor

kgston commented Feb 21, 2022

You can already override it to use the native-image binary if you like:
GraalVMNativeImage / containerBuildImage := Some(s"ghcr.io/graalvm/native-image:ol8-java17-22.0.0.2")

I wrote it that way to keep using the baseline image (not sure how important that is really..). And I noticed that the native-image docker images do not get updated as quickly as the baseline image either.

@pshirshov
Copy link
Author

Yes, but that's kinda painful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants