5

背景

这几天回归小型进销存系统之后,由于落下同伴太多的知识点,就想着先启动一下整个项目来操作操作。然后去学习一些新的代码、新的知识、新的解决方法。
一开始后台启动失败,定位到 elasticsearch 这一块。然后,才发现离组时间中,添加了很多新的镜像:redis、elasticsearch...
接着 docker-compose up -d 拉去镜像,但是还是报错。
自己弄半天,最后还是求助学长们才得以解决

具体解决流程

环境

mac mini m4
Docker Desktop 4.25.2
elasticsearch 8.14.3

1. 后台报错信息

截取 “Caused by” 后面的核心信息:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'contactDocumentServiceImpl' defined in file 
[/Users/zhangyuxuan/Desktop/code/mini-crm/api/target/classes/club/yunzhi/minicrm/service/ContactDocumentServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'contactDocumentRepository' defined in club.yunzhi.minicrm.repository.ContactDocumentRepository defined in @EnableElasticsearchRepositories declared on WebConfig: Failed to instantiate
[org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository]: Constructor threw exception

2. 查看 docker 容器日志

发现,elasticsearch 容器根本没起来。查看 log

2025-10-13 16:09:35 # A fatal error has been detected by the Java Runtime Environment:
2025-10-13 16:09:35 #
2025-10-13 16:09:35 #  SIGILL (0x4) at pc=0x0000ffff9416ee68, pid=7, tid=16
2025-10-13 16:09:35 #
2025-10-13 16:09:35 # JRE version:  (22.0.1+8) (build )
2025-10-13 16:09:35 # Java VM: OpenJDK 64-Bit Server VM (22.0.1+8-16, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, serial gc, linux-aarch64)
2025-10-13 16:09:35 # Problematic frame:
2025-10-13 16:09:35 # j  java.lang.System.registerNatives()V+0 java.base@22.0.1
2025-10-13 16:09:35 #
2025-10-13 16:09:35 # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
2025-10-13 16:09:35 #
2025-10-13 16:09:35 # An error report file with more information is saved as:
2025-10-13 16:09:35 # /usr/share/elasticsearch/hs_err_pid7.log
2025-10-13 16:09:35 [0.012s][warning][os] Loading hsdis library failed
2025-10-13 16:09:35 #
2025-10-13 16:09:35 # The crash happened outside the Java Virtual Machine in native code.
2025-10-13 16:09:35 # See problematic frame for where to report the bug.

从错误信息来看,这是一个 SIGILL (非法指令) 错误,通常与 CPU 架构不兼容有关
错误关键点:

  • SIGILL (0x4) 非法指令错误
  • linux-aarch64 显示运行在ARM64架构上

可能的原因:

  1. CPU架构不兼容
    JVM 在启动时遇到 SIGILL(非法指令)信号,发生在 java.lang.System.registerNatives() 方法中。
    使用的JDK可能与CPU的指令集不匹配
  2. 版本不匹配
    当前的 elasticsearch 镜像与当前的电脑的架构不匹配
    docker 版本

3. 逐步排错

  1. 查看 elasticsearch 的镜像和本机电脑的架构是否一致
    但是,从 docker hub 中查看到的 8.14.3 它既支持 linux/amd64,也支持 linux/arm64
并且,docker 有 仿真机制 当拉去的镜像与计算机架构不匹配的时候。会利用 QEMU 来进行动态翻译 x86 指令 -> ARM 指令
最终容器可以在ARM CPU 上运行,就像原生 x86 一样

image.png

‼️ 但是,拉下来镜像后,问题依旧存在

  1. 查看 Docker Desktop 的版本是否有影响
    image.png

首先,可以看到当前的版本是 4.25.2。
关键背景:Elasticsearch 镜像和架构问题
同时,elasticsearch 8.14.3 官方只提供了 amd64(x86_64)架构版本,没有 arm64版本;
这意味着:

  • 在 Apple Silicon 上运行它时,Docker 必须做 跨架构仿真
  • Elasticsearch 的底层是 Java(JVM)

    • JVM 启动时会使用大量的 JIT 编译和汇编级指令
    • 这些指令通常和 CPU 架构紧密绑定

    ➡️ 如果用QEMU 仿真 x86 -> ARM 的指令时,某些复杂的指令或 JIT 优化可能 未完全支持性能极差,就可能触发 SIGILL(非法指令错误)

也就是说:

Elasticsearch 容器崩溃的根本原因是:
JVM 的 JIT 生成了 QEMU 无法正确仿真的 x86 指令

4. 解决

我们先升级一下 Docker Desktop 的版本至最新的版本。在试着去重新拉取镜像,开启容器。容器成功运行!

image.png

到此,我们就定位到了,具体的错误。

image.png

5. 看看官方怎么说

在官方文档中说明,在 Docker Desktop 4.35.0 版本之前仍存在一些小问题:Docker Desktop 对 Rosetta 的支持并不是很好 具体文档请点击查看

image.png

Docker Desktop 4.26 中对 Rosetta 有一定程度的优化。Rosetta 的性能得到了显著的提升。 具体文档请点击查看

image.png

image.png

😂 而我们出现问题的 Docker Desktop 的版本正好是它的上一个版本

image.png

浅谈 QEMU(Quick Emulator) 与 Rosetta 的区别

仿真模式

是什么?

Docker 的仿真模式(Emulation Mode)允许在不同 CPU 架构之间运行容器。

例如在 ARM 芯片上运行 x86 镜像。它底层依赖 QEMU 模拟器和 Linux 的 binfmt_misc 机制,通过 Docker Desktop 或 buildx 自动启用。开发者只需指定 --platform 参数,即可实现跨架构运行和构建。

为什么需要?

为了解决像上述遇到的这种“架构不匹配”,Docker 引入了仿真模式。
让我们可以在 ARM 上运行 x86 镜像

image.png

区别

一句话总结:QEMU 是“通用的CPU模拟器”,能让任何架构假装成另一种架构;而 Rosetta 是“苹果专用的翻译官”,只负责让 macOS 上的 Intel 应用能在苹果芯片上流畅运行。
维度4.25 版本 4.26(及以上)+ Rosetta 版本
仿真机制QEMURosetta for Linux
兼容性一般,JVM 类容器易崩溃几乎兼容所有 x86 用户态
性能
Elasticserach 启动❌ SIGILL 崩溃✅ 正常运行
原理动态指令仿真动态指令翻译

image.png

拓展学习

🤔 x86 是什么?

是一种 CUP 的指令集,是一种复杂指令集。可以在一次操作中完成多个任务

🤔 arm64 是什么?

另一中指令集 -- 精简指令集。其指令集设计更简单,指令长度较短

86、amd64、arm64 三者关系 + Rosetta 如何在 Mac 上桥接

image.png

总结

Docker 的“仿真模式”其实是靠 QEMU 模拟其他 CPU 架构来实现的。
它让 ARM 用户也能运行 x86 镜像,但性能和兼容性取决于 QEMU 版本。
你的 Elasticsearch 镜像在 4.25.2 启动失败、4.48.0 成功,其根本原因就在于 QEMU 更新后改进了 JIT 仿真能力。

而相比之下,macOS 的 Rosetta 是另一种“针对应用级别”的高性能仿真,
这就是为什么 “运行 x86 的 Navicat 没问题,但运行 x86 的 Elasticsearch 容器会崩溃” 的原因。

参考文献:

dockerdocs 官方文档

dockerhub 镜像仓库

感谢

这个问题,对于我而言,我只能想到可能是elasticsearch的版本与我的电脑版本不匹配。而,由于对 Docker 等一些基础的底层逻辑的不了解,倒是我想不到问题可能出现在Docker Desktop的版本也会有影响。
在这里,要感谢刘宇轩学长和柯晓彬学长,这个问题我尝试去检索关键词以及问大模型,得到的答案都不尽如人意。最后还是靠学长们解决的。
还有需要注意的一点,对于这种环境问题,当前阶段可以尝试先自己解决。但是,一定要注意时间。发现一个小时都解决不了,应该马上求助他人!!!


vuxuan
61 声望9 粉丝