es4x icon indicating copy to clipboard operation
es4x copied to clipboard

Docker issues appear after upgrade from 0.13.3 to 0.14.0

Open UglyHobbitFeet opened this issue 3 years ago • 21 comments

It appears as though you can no longer use a slim java as a 'first layer' in docker.

In my Dockerfile I have the equivalent of

ARG BASEIMAGE=<any-slim-jdk-java11>
... <other commands omitted for brevity>
RUN tar xvfz <path-to-es4x-pm-0.14.0-bin.tar.gz> --strip-components=1 -C /usr/local \
 && es4x install \
 && es4x jlink --target=${JVM_TMP_DIR}
...
COPY --from=<baseimage>/lib/x86_64-linux-gnu/libz.so.1 /usr/lib
ENTRYPOINT [  "/usr/bin/java", "--module-path=node_modules/.jvmci", "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "--upgrade-module-path=node_modules/.jvmci/compiler.jar", "-XX:+UseContainerSupport", "-jar", "./node_modules/.bin/es4x-launcher.jar" ]

which worked fine in 0.13.3

I now get the following stacktrace

Installing JVMCI Compiler...
Installing GraalJS...
Skipping install (recent successful run)
Exception in thread "main" java.lang.module.FindException: Module org.graalvm.sdk not found, required by com.oracle.truffle.regex
        at java.base/java.lang.module.Resolver.findFail(Resolver.java:877)
        at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
        at java.base/java.lang.module.Resolver.resolve(Resolver.java:140)
        at java.base/java.lang.module.Configuration.resolve(Configuration.java:422)
        at java.base/java.lang.module.Configuration.resolve(Configuration.java:256)
        at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration.<init>(JdepsConfiguration.java:117)
        at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration$Builder.build(JdepsConfiguration.java:563)
        at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.buildConfig(JdepsTask.java:589)
        at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:543)
        at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:519)
        at jdk.jdeps/com.sun.tools.jdeps.Main.main(Main.java:49)

/opt/java/openjdk/bin/jdeps exit with status: 1

Doing an

     --add-modules \
        org.graalvm.sdk

seems to work for the org.graalvm.sdk. but then it complains about org.graalvm.truffle. Module org.graalvm.truffle not found, required by com.oracle.truffle.regex

Doing an

     --add-modules \
        org.graalvm.sdk,org.graalvm.truffle

doesn't seem to work as it shows a same error as above

If I change to ARG BASEIMAGE=oracle/graalvm-ce:20.3.0-java11 it seems to get past that but then I run into other issues like missing the libz.so.1 file. Ex: COPY --from=<baseimage>/lib/x86_64-linux-gnu/libz.so.1 /usr/lib so I have to change it to COPY --from=<baseimage>/usr/lib/x64/libz.so.1 /usr/lib

That works but now I get complaints about the truffle-api not being on the classpath. So i add it like:

COPY --from=<baseimage> /opt/graalvm-ce-java11-20.3.0/lib/truffle/ /tmp/truffle/
ENTRYPOINT [ <replacing the -jar cmd with this> "-cp","./node_modules/.bin/es4x-launcher.jar:/tmp/truffle/*","io.reactiverse.es4x.ES4X", <all-other-params-the same> ...]

Which leads me to a

Exception in thread "main" java.lang.IllegalAccessError: superclass access check failed: class com.oracle.truffle.polyglot.PolyglotImpl (in unnamed module @0x2cbb3d47) cannot access class org.graalvm.polyglot.impl.AbstractPolyglotImpl (in module org.graalvm.sdk) because module org.graalvm.sdk does not export org.graalvm.polyglot.impl to unnamed module 

Which seems to be a quarkus bug? https://github.com/quarkusio/quarkus/issues/10226 and https://stackoverflow.com/questions/62520374/com-oracle-truffle-polyglot-polyglotimpl-in-unnamed-module-cannot-access-class

You can see where this is going...

It can be a rabbit-hole to try and get the dockerfile working again between 0.13.3->0.14.0. Is that now a hard-requirement to use the graalvm as the base-layer?

As a sidenote, I see the entrypoint command mentions the .jvmci twice. The docker image at the final stage does not have the node_modules/.jvmci directory so I guess it just ignored those flags. If I copy the .jvmci folder into the final image I start getting errors about Error occurred during initialization of boot layer java.lang.module.FindException: Module java.management not found, required by org.graalvm.truffle

UglyHobbitFeet avatar Dec 09 '20 15:12 UglyHobbitFeet

Hi,

Just wondering if there was any movement on this, or when we could expect a release with this this fix.

Thanks!!

UglyHobbitFeet avatar Jan 25 '21 14:01 UglyHobbitFeet

Not yet. Things get complicated when trying to support all combinations of VMs and builds. The current version creates docker containers using jlink of adoptopenjdk java11 images and runs on distroless base image to reduce the overall space. If the goal is to run on graalvm base image, I think just adding the application layer is small and faster that forcing a jdeps runtime. The base image will be on the server already so the final layer is very small and fast to deploy.

If this is really needed then if you could figure out the right modules that should be passed to jlink I can quickly add a validation, if target is stock jvm, current behavior, else new one.

Regarding the release. Vert.x is about to release 4.0.1 so I am waiting for that moment to perform a full build and release. This will fix many TS "bugs" related to missing annotations upstream.

pmlopes avatar Jan 25 '21 14:01 pmlopes

I would opt to keep using adoptopenjdk/distroless and not to use the graalvm base image. I just run into multiple hurdles when attempting to do so (as shown in the original post). If I'm understanding you correctly, will the 4.0.1 Vert.x release help resolve these?

UglyHobbitFeet avatar Jan 25 '21 14:01 UglyHobbitFeet

FWIW I tried following the directions here using 0.14.0 as the target but the instructions don't work. https://reactiverse.io/es4x/get-started/package.html#jlink

In step #2 it complains about the -o/--only flag not being valid even though the docs show it is. If I remove it I end up in the same place as this ticket where the jlink can't find the org.graalvm.truffle module. No matter what I do with the jlink command (pointing to the correct jar, adding the module, etc) I cannot get past this. I wonder if there is an issue with the es4x jlink which prevents it from successfully linking (whereas the non es4x jlink might work differently)

UglyHobbitFeet avatar Jan 25 '21 18:01 UglyHobbitFeet

It seems as though I've discovered a couple issues with the directions shown at : https://reactiverse.io/es4x/get-started/package.html#jlink

  • It assumes the graal/truffle jars are in node_modules/.lib folder. They are not. They exist in the node_modules/.jvmci folder. I have to run a copy command in docker to put them there. I cannot use jlinks module-path as the es4x jlink seems hardcoded to only allow the node_modules/.lib folder.
  • The es4x curl command outputs to /usr/local. The es4x jlink also outputs to /usr/local. If left with these defaults, jlink will error out saying /usr/local already exists. The former should probably be output to /es4x and have specific references changed to point to it
  • Using the debian-stable image when I run it I get an error like: Failed in deploying verticle caused by SyntaxError: /usr/src/app/node_modules/@vertx/core/options.js:17:65 Expected ; but found SSLEngineOptions KeyCertOptions: Java.type('io.vertx.core.net.KeyCertOptions') SSLEngineOptions: Java.type('io.vertx.core.net.SSLEngineOptions') TrustOptions: Java.type('io.vertx.core.net.TrustOptions')/// <reference types="@vertx/core/options" /> at org.graalvm.sdk/org.graalvm.polyglot.Context.eval(Context.java:347) at io.reactiverse.es4x.Runtime$1.apply(Runtime.java:103) at io.reactiverse.es4x.Runtime$1.apply(Runtime.java:58) at js _load(file:/usr/src/app/node_modules/.lib/es4x-0.14.0.jar!/io/reactiverse/es4x/jvm-npm.js:68-71:2056-2187)

UglyHobbitFeet avatar Jan 25 '21 19:01 UglyHobbitFeet

I have also tried doing an es4x dockerfile command. It has the same errors about the es4x -o/--only flag as shown 2 posts up. It has the same errors about the missing truffle/graalvm jars as in the previous post. Resolving them leads to the same error about SSSLEngineOptions as shown in the previous post.

I have tried every iteration that I can think of to get this working, but the es4x dockerfile command seems inherently broken within 0.14.0 as I cannot get the docker file up and running.

The only modification I made to the es4x dockerfile was changing: RUN es4x install --only=prod to RUN es4x install && cp node_modules/.jvmci/* node_modules/.lib

UglyHobbitFeet avatar Jan 26 '21 15:01 UglyHobbitFeet

FYI I filed a bug for the SyntaxError here : https://github.com/eclipse-vertx/vert.x/issues/3770

UglyHobbitFeet avatar Jan 26 '21 15:01 UglyHobbitFeet

I got it to work. I had to:

  • Manually override the options.js file with the syntax fix
  • Copy the .jvmci contents into .lib
  • Remove the --only property from es4x install

Hopefully these changes (or modifications of them) can be rolled into the es4x 0.14.1 release so it works out of the box.

UglyHobbitFeet avatar Jan 26 '21 17:01 UglyHobbitFeet

@UglyHobbitFeet can you paste your resulting dockerfile here? I still have issues...

BeneStem avatar May 11 '21 14:05 BeneStem

Sorry, I don't have it anymore. We've moved on to using a different tech stack.

On Tue, May 11, 2021 at 10:13 AM Benedikt Stemmildt < @.***> wrote:

@UglyHobbitFeet https://github.com/UglyHobbitFeet can you paste your resulting dockerfile here? I still have issues...

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/reactiverse/es4x/issues/471#issuecomment-838547149, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALBDS7W5X7PNCOW425XQZKLTNE3PPANCNFSM4UTVGX3A .

UglyHobbitFeet avatar May 11 '21 14:05 UglyHobbitFeet

@UglyHobbitFeet thx for replying anyways!

BeneStem avatar May 11 '21 14:05 BeneStem

@BeneStem have you seen this template?

https://github.com/reactiverse/es4x/blob/develop/pm/src/main/resources/META-INF/es4x-commands/Dockerfile

It doesn't rely on graal images anymore, just plain openjdk and the final image runs on google distroless which makes it reasonably small.

Can you share what is not working for you?

pmlopes avatar May 12 '21 13:05 pmlopes

@pmlopes this actually did not work for me as the jlink step needs graal and therefore the openjdk11 baseimage is not working... Could be because of mac m1 docker issues but i doubt that.

And I'd recommend to use "npm ci" instead of "npm install" in ci/cd or docker scenarios :)

I can share the exact error this evening!

BeneStem avatar May 15 '21 15:05 BeneStem

I am now using alpine... which is okayish but having distroless would be better ;)

FROM node:lts AS NPM
RUN ln -s /bin/true /usr/bin/es4x
WORKDIR /usr/src/app
COPY . .
RUN npm --unsafe-perm ci --only=prod

FROM adoptopenjdk/openjdk11 AS ES4X
RUN curl -sL https://github.com/reactiverse/es4x/releases/download/0.14.2/es4x-pm-0.14.2-bin.tar.gz | tar zx --strip-components=1 -C /usr/local
COPY --from=NPM /usr/src/app /usr/src/app
WORKDIR /usr/src/app
RUN es4x install --only=prod

FROM adoptopenjdk/openjdk11:jre-11.0.11_9-alpine
COPY --from=ES4X /usr/src/app /usr/src/app
WORKDIR /usr/src/app
ENTRYPOINT [  "java", "--module-path=node_modules/.jvmci", "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "--upgrade-module-path=node_modules/.jvmci/compiler.jar", "-XX:+UseContainerSupport", "-jar", "./node_modules/.bin/es4x-launcher.jar" ]

BeneStem avatar May 15 '21 15:05 BeneStem

@pmlopes here is the error I get with the 0.14.2 default Dockerfile:

#18 21.41 Error: Missing dependencies: classes not found from the module path and classpath.
#18 21.41 To suppress this error, use --ignore-missing-deps to continue.
#18 21.41 
#18 21.41 io.netty.codec
#18 21.41    io.netty.handler.codec.compression.JZlibDecoder    -> com.jcraft.jzlib.Inflater                          not found
#18 21.41    io.netty.handler.codec.compression.JZlibDecoder    -> com.jcraft.jzlib.JZlib                             not found
AND SO ON....
#18 21.43 
#18 21.43 /opt/java/openjdk/bin/jdeps exit with status: 1
------
executor failed running [/bin/sh -c es4x jlink --target=/es4x]: exit code: 1

BeneStem avatar May 15 '21 16:05 BeneStem

@BeneStem can you make a short project and dockerfile showing the error? It would be great help to solve this

pmlopes avatar May 15 '21 20:05 pmlopes

Sure thing... When I was removing the --only=prod from RUN es4x install --only=prod it got better but still did not work...

BeneStem avatar May 15 '21 21:05 BeneStem

Here you go @pmlopes :)

es4x-flower.zip

BeneStem avatar May 15 '21 21:05 BeneStem

@BeneStem sorry for the long wait, I've checked and we can get it to work more reliably with:

# Use official node for build
FROM node:lts AS NPM
# Disable calls to es4x command (this container has no JVM)
RUN ln -s /bin/true /usr/bin/es4x
# Create app directory
WORKDIR /usr/src/app
# Add the application to the container
COPY . .
# npm is run with unsafe permissions because the default docker user is root
# also all dev packages are not installed
RUN npm --unsafe-perm install --only=prod

# Second stage (build the JVM related code)
FROM adoptopenjdk/openjdk11 AS JVM
# Download the ES4X runtime tool
RUN curl -sL https://github.com/reactiverse/es4x/releases/download/0.14.2/es4x-pm-0.14.2-bin.tar.gz | tar zx --strip-components=1 -C /usr/local
# Copy the previous build step
COPY --from=NPM /usr/src/app /usr/src/app
# use the copied workspace
WORKDIR /usr/src/app
# force es4x maven resolution only to consider production dependencies
RUN es4x install --only=prod

# Third stage (contain)
FROM gcr.io/distroless/java:11
# Collect the jars from the previous step
COPY --from=JVM /usr/src/app /usr/src/app
WORKDIR /usr/src/app
# define the entrypoint
ENTRYPOINT [  "/usr/bin/java", "--module-path=node_modules/.jvmci", "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "--upgrade-module-path=node_modules/.jvmci/compiler.jar", "-XX:+UseContainerSupport", "-jar", "./node_modules/.bin/es4x-launcher.jar" ]

This avoids the jlink step but still uses the distroless container, so in the end the size is ~250MB

pmlopes avatar Jun 01 '21 12:06 pmlopes

I think until the jlink step is more reliable we should use this method, as it will be easier for end users to customize.

For reference 250MB isn't that big:

$ docker images
REPOSITORY               TAG                    IMAGE ID       CREATED          SIZE
es4x-flower              latest                 d13911ffb716   28 seconds ago   267MB
adoptopenjdk/openjdk11   jre-11.0.11_9-alpine   98d92815b3d8   13 days ago      148MB
node                     lts                    9153ee3e2ced   2 weeks ago      943MB
adoptopenjdk/openjdk11   latest                 c537c6b0cca2   4 weeks ago      437MB
hello-world              latest                 d1165f221234   2 months ago     13.3kB
gcr.io/distroless/java   11                     3ed3813dd91b   51 years ago     200MB

pmlopes avatar Jun 01 '21 12:06 pmlopes

No problem. Thank you very much!

Using alpine, like I do a few comments above makes it 220mb...

Both ways are fine for me.

Is there any downside to using alpine?

BeneStem avatar Jun 02 '21 09:06 BeneStem