Docker容器运行失败无法进入,UIC559消息转换镜像报错求助
UIC559消息转换Spark处理器Docker镜像运行问题及解决
问题场景
我正在构建用于UIC559消息转换的Spark处理器Docker镜像,执行命令sudo docker run -it test:v2 /bin/sh尝试进入容器时,出现以下报错:
inside file Error: Could not find or load main class .bin.sh Caused by: java.lang.ClassNotFoundException: /bin/sh
相关文件内容
entrypoint.sh脚本
#!/bin/bash echo inside file exec java -Djava.security.egd=file:/dev/./urandom -cp /opc/OPCUAClientUIC559_2.1-assembly.jar $*
完整Dockerfile
FROM openjdk:11.0.1 AS build ARG SCALA_VERSION ENV SCALA_VERSION ${SCALA_VERSION:-2.12.15} ARG SBT_VERSION ENV SBT_VERSION ${SBT_VERSION:-1.3.13} ARG USER_ID ENV USER_ID ${USER_ID:-9999} ARG GROUP_ID ENV GROUP_ID ${GROUP_ID:-9999} # copy the root certificate for sbt and scala package to download thorugh network COPY ./CIdependencies/zscaler-rootca.cer /root/zscaler-rootca.cer # Install sbt and pass root certificate RUN curl -fsLv --cacert /root/zscaler-rootca.cer "https://github.com/sbt/sbt/releases/download/v$SBT_VERSION/sbt-$SBT_VERSION.tgz" | tar xfz - -C /usr/share RUN \ chown -R root:root /usr/share/sbt && \ chmod -R 755 /usr/share/sbt && \ ln -s /usr/share/sbt/bin/sbt /usr/local/bin/sbt && \ # Install Scala and pass root certificate curl -fsL --cacert /root/zscaler-rootca.cer "https://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz" SCALA_DIR=/usr/share/scala-$SCALA_VERSION | tar xfz - -C /usr/share && \ mv -f /usr/share/scala-$SCALA_VERSION /usr/share/scala && \ chown -R root:root /usr/share/scala && \ chmod -R 755 /usr/share/scala && \ ln -s /usr/share/scala/bin/* /usr/local/bin && \ echo "@main def main = println(util.Properties.versionMsg)" > test.scala && \ echo "println(util.Properties.versionMsg)" > test.scala && \ scala -nocompdaemon test.scala && rm test.scala && \ # Install rpm for sbt-native-packager -see https://github.com/hseeberger/scala-sbt/pull/114 echo "deb http://deb.debian.org/debian/ oldstable main contrib non-free deb http://deb.debian.org/debian/ oldstable-updates main contrib non-free" > /etc/apt/sources.list && \ rm /etc/apt/sources.list.d/* && \ apt-key adv --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0E9840 && \ apt-get update && apt-get install rpm -y && \ rm -rf /var/lib/apt/lists/* USER root WORKDIR /root RUN keytool -noprompt -storepass changeit -importcert -alias zscaler -file ./zscaler-rootca.cer -keystore /etc/ssl/certs/java/cacerts # Prepare sbt (warm cache) RUN \ sbt sbtVersion && \ mkdir -p project && \ echo "scalaVersion := \"${SCALA_VERSION}\"" > build.sbt && \ echo "sbt.version=${SBT_VERSION}" > project/build.properties && \ echo "// force sbt compiler-bridge download" > project/Dependencies.scala && \ echo "case object Temp" > Temp.scala && \ sbt compile && \ rm -r project && rm build.sbt && rm Temp.scala && rm -r target CMD sbt COPY ./ ./ RUN sbt assembly FROM ubuntu:latest ARG GIT_COMMIT ARG DS_VERSION=0.0.0.0 LABEL Name=OPCUA_ClientUIC559 Version=$DS_VERSION git_commit=$GIT_COMMIT RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install -y -f --no-install-recommends \ ca-certificates\ curl\ icu-devtools=66.1-2ubuntu2 \ openjdk-11-jre \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Create a user, group and changing the ownership to access the built files as root should not be used ideally RUN groupadd -r opc && useradd --no-log-init -r -g opc opc RUN mkdir /opc; chown opc.opc /opc USER opc # Switch working directory WORKDIR /opc COPY --from=build --chown=opc:opc /root/entrypoint.sh /opc/entrypoint.sh COPY --from=build --chown=opc:opc /root/target/scala-2.12.15/*.jar /opc/OPCUAClientUIC559_2.12.15-assembly.jar RUN chmod +x /opc/entrypoint.sh ENTRYPOINT ["bash","/opc/entrypoint.sh"]
已尝试操作
- 确认构建带entrypoint的镜像后,容器内存在jar包
- 在docker run命令后传递Java参数:
sudo docker run -it test:v2 com.domain.uic559.opcua.OPCUAKafkaStreamUIC559
问题根源
当执行sudo docker run -it test:v2 /bin/sh时,/bin/sh会被当作参数传递给entrypoint脚本。脚本中的$*会把这个参数直接拼到java命令后,导致Java将/bin/sh误认为是要运行的主类名,从而抛出找不到主类的错误。
另外,entrypoint脚本中指定的jar包路径/opc/OPCUAClientUIC559_2.1-assembly.jar与Dockerfile中实际复制的OPCUAClientUIC559_2.12.15-assembly.jar不匹配,这也是潜在的运行问题。
解决方案
方法1:临时进入容器(无需修改镜像)
使用--entrypoint参数覆盖默认的entrypoint,直接运行shell:
sudo docker run -it --entrypoint /bin/sh test:v2
方法2:修复entrypoint脚本(长期解决)
修改entrypoint.sh脚本,增加逻辑判断:如果用户传递的参数是可执行命令(如/bin/sh),则直接执行该命令;否则执行Java程序。同时修正jar包路径:
#!/bin/bash echo inside file # 判断第一个参数是否为可执行命令 if command -v "$1" >/dev/null 2>&1; then exec "$@" else # 执行Java程序,使用正确的jar包路径 exec java -Djava.security.egd=file:/dev/./urandom -cp /opc/OPCUAClientUIC559_2.12.15-assembly.jar "$@" fi
修改后重新构建镜像,即可实现两种场景:
- 正常运行Java程序:
sudo docker run -it test:v2 com.domain.uic559.opcua.OPCUAKafkaStreamUIC559 - 进入容器shell:
sudo docker run -it test:v2 /bin/sh
内容的提问来源于stack exchange,提问作者lakshman
相关产品推荐
相关产品推荐

