Stories

Detail Return Return

記一次Docker版本不兼容導致的Elasticsearch容器啓動失敗 - Stories Detail

背景

這幾天迴歸小型進銷存系統之後,由於落下同伴太多的知識點,就想着先啓動一下整個項目來操作操作。然後去學習一些新的代碼、新的知識、新的解決方法。
一開始後台啓動失敗,定位到 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 版本
仿真機制 QEMU Rosetta 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的版本也會有影響。
在這裏,要感謝劉宇軒學長和柯曉彬學長,這個問題我嘗試去檢索關鍵詞以及問大模型,得到的答案都不盡如人意。最後還是靠學長們解決的。
還有需要注意的一點,對於這種環境問題,當前階段可以嘗試先自己解決。但是,一定要注意時間。發現一個小時都解決不了,應該馬上求助他人!!!

Add a new Comments

Some HTML is okay.