为什么 运行 Java 可以在 Docker 图像中手动编程而不是作为 ENTRYPOINT

Why can run Java program manually in a Docker image but not as an 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

并且有效。

为什么 运行ning 作为 ENTRYPOINT 使 libjli.so 库影子并尝试重新定位 JLI*?

问题出在 musl 中。当您直接从 shell 执行时,musl 能够读取库路径,但是当您使用 CMD and/or 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"]

终于开始工作了。