M1(arm64)构建Docker镜像jlink生成JRE运行异常问题
问题根因
两个报错的核心本质都是二进制目标运行环境与实际运行环境不匹配,并非单纯的CPU架构不匹配:
- 本地构建镜像报
Exec format error的原因:你当前M1 Mac上安装的Zulu JDK是macOS aarch64版本,用它自带的jlink生成的JRE是适配Darwin(macOS)内核的Mach-O格式二进制,而Docker容器内运行的是Linux系统,即便CPU同样是aarch64架构,跨操作系统的二进制也无法直接运行,这就是格式错误的来源,和CPU架构无关。 - 拉取远程镜像报
/lib64/ld-linux-x86-64.so.2: No such file or directory的原因:远程镜像内的JRE是x86_64架构Linux版本,M1 Mac是aarch64架构,默认没有配置x86架构二进制仿真能力,找不到x86程序依赖的动态链接器,自然无法运行。
解决方案
根据场景选对应处理方式即可:
- 最优方案:将jlink构建步骤全部移入Docker构建流程内完成,使用和运行阶段同系统、同架构的Linux JDK基础镜像执行jlink,从根源避免跨系统/跨架构的二进制不兼容问题。参考多阶段构建Dockerfile示例:
# 构建阶段:使用Linux aarch64版本JDK作为构建基础 FROM eclipse-temurin:17-jdk-jammy AS build WORKDIR /build # 复制项目文件 COPY . . # 在Linux容器环境内执行jlink,生成的JRE天然适配容器运行环境 RUN jlink \ --add-modules java.base,java.logging,your.required.modules \ --output /build/custom-jre \ --strip-debug \ --compress=2 \ --no-header-files \ --no-man-pages # 运行阶段:使用同架构精简Linux基础镜像 FROM eclipse-temurin:17-jre-alpine WORKDIR /app # 从构建阶段复制生成的JRE和应用包 COPY --from=build /build/custom-jre ./jre COPY --from=build /build/your-app.jar ./app.jar # 启动命令 ENTRYPOINT ["./jre/bin/java", "-jar", "app.jar"]
- 如果你必须在宿主机提前执行jlink生成JRE,需要额外下载安装Linux aarch64版本的JDK,使用该Linux版本JDK内的jlink工具生成JRE,再复制到Docker镜像中,不能使用当前宿主机安装的macOS版本JDK执行jlink。
- 如果需要运行远程拉取的x86_64架构镜像,可以先安装Docker跨架构仿真组件,执行命令
docker run --privileged --rm tonistiigi/binfmt --install all,配置完成后即可运行x86_64架构的Linux二进制,但该模式下程序运行有性能损耗,仅建议本地调试使用,生产环境请使用原生aarch64架构构建的镜像。
内容的提问来源于stack exchange,提问作者Chris Stewart
相关产品推荐
相关产品推荐

