首页 > 解决方案 > 为什么可以在 Docker 映像中手动运行 Java 程序,但不能作为 ENTRYPOINT

问题描述

我创建了一个 openjdk-11 alpine docker 映像并将我的 jar 复制到其中。我的 Dockerfile 是这样的:

FROM pwittchen/alpine-java11
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} /opt/app.jar
ENTRYPOINT ["java", "-jar", "/opt/app.jar"]

如果我运行:

docker run -it image

然后

Error loading shared library libjli.so: No such file or directory (needed by /usr/local/share/jdk-11/bin/java)
Error relocating /usr/local/share/jdk-11/bin/java: JLI_Launch: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_PreprocessArg: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_ReportMessage: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_StringDup: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_MemFree: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_InitArgProcessing: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_AddArgsFromEnvVar: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_List_add: symbol not found
Error relocating /usr/local/share/jdk-11/bin/java: JLI_List_new: symbol not found

但如果:

docker run -it --entrypoint /bin/sh image

然后我可以直接在shell中执行:

$ java -jar /opt/app.jar

并且有效。

为什么以 ENTRYPOINT 运行会使 libjli.so 库隐藏并尝试重新定位 JLI*?

标签: dockeralpinejava-11

解决方案


问题出在肌肉上。当您直接从 shell 执行时,musl 能够读取库路径,但是当您使用 CMD 和/或 ENTRYPOINT 执行时,musl 无法解析库路径。

在阅读和 openjdk8-alpine 中已经解决的旧问题后,我能够找到这个。那么这是一个回归。

https://github.com/docker-library/openjdk/issues/77

要解决,首先创建一个文件ld-musl-x86_64.pat指定 musl 所需的库在哪里。文件内容如下所示:

/lib
/usr/lib
/usr/local/lib
/usr/local/share/jdk-11/lib/jli

在构建阶段将文件复制到 docker 映像。我的新 Dockerfile 如下所示:

FROM pwittchen/alpine-java11
VOLUME /tmp
ARG JAR_FILE
#Copy the configuration file with the Library path!
COPY ld-musl-x86_64.path /etc/ld-musl-x86_64.pat
COPY ${JAR_FILE} /opt/app.jar
ENTRYPOINT ["java", "-jar", "/opt/app.jar"]

终于工作了。


推荐阅读