科技 · 實用指南
Docker顯示exec format error?先查映像檔、二進位與進入點,再決定重建
exec format error不能只憑映像檔標籤診斷。先追蹤選中的manifest、最終檔案系統、執行檔架構與進入點直譯器,再考慮清除快取、加入QEMU或重建。

對Linux容器而言,「exec format error」表示核心無法執行收到的檔案。CPU架構只是可能原因之一;缺少可用直譯器標頭的腳本或其他無效執行檔格式也可能失敗。應先找出特定檔案與失敗階段,再選擇修復方式。
保留失敗映像檔與錯誤輸出。一份有用的故障紀錄應串起四個環節:執行主機、選中的映像檔manifest、最終檔案系統內的實際執行檔,以及嘗試啟動它的命令。架構標籤相符,不能取代這四項核對。
1. 重建前記錄失敗執行
保存完整錯誤、映像檔參照及digest、已有容器ID、要求的平台與使用的Docker context。檢查失敗容器的設定和掛載,不要只看Dockerfile:執行時覆寫進入點或掛載腳本,可能改變實際執行的檔案。用docker container inspect CONTAINER取得設定,用docker image inspect IMAGE查看本機映像檔中繼資料。
相關主機是實際執行程序的Docker daemon或建置工作節點,可能在遠端,也可能位於Docker Desktop的Linux虛擬機器內。只知道筆電處理器不足以確定它。還應區分Dockerfile的RUN指令失敗與成品容器啟動失敗:RUN階段點名/bin/sh的錯誤,應查建置階段環境;應用程式進入點失敗則須查最終執行檔案系統。
2. 對照登錄庫變體與本機映像檔
用docker buildx imagetools inspect IMAGE_REFERENCE查看登錄庫參照的manifest與平台變體,再與確切的本機映像檔和失敗執行要求的平台比較。可變標籤可能在失敗後指向新映像檔,因此應保留原digest,不要把今天的標籤當成歷史證據。
所需平台變體不存在時,應選擇或建置正確變體;變體存在卻選錯時,檢查明確的平台設定與部署組態。--platform=linux/amd64是在指定目標,不會轉換已複製進映像檔的任意arm64檔案。找不到相容manifest可能在執行前就產生選擇錯誤,與ENOEXEC發生的階段不同。
3. 不啟動失敗命令也能檢查檔案
若已有停止的失敗容器,可用docker cp CONTAINER:/path/to/file ./artifact-to-inspect複製可疑檔案。Docker文件明確支援從停止的容器複製。若只有映像檔,docker create IMAGE會建立但不啟動容器;記錄傳回ID,再檢查此暫存容器。掛載須另外核對,因為執行時提供的檔案可能不同於映像檔內容。
使用可信任的檔案檢查工具(如file)檢查複製出的檔案;對ELF二進位檔,readelf -h可顯示機器類型,readelf -l可顯示其要求的程式直譯器。檢查檔案本身,不要為了確定架構而執行它。本機沒有這些工具時,使用既有可信任分析環境。不要假定精簡或distroless映像檔內有shell、file或readelf。
4. 沿建置階段追查複製的二進位檔
列出所有會建立或下載執行檔,並把它們複製進最終映像檔的階段。BUILDPLATFORM描述BuildKit工作節點,TARGETPLATFORM描述要求的輸出。固定在建置主機平台的階段,可以刻意執行原生編譯器,但編譯設定仍須產生目標平台產物。
Docker預定義目標參數在全域可用,但在階段內使用前須以ARG宣告。檢查TARGETOS、TARGETARCH及所需的TARGETVARIANT,再核對語言工具鏈真正產生的結果。只宣告參數,不會讓所有編譯器自動交叉編譯。同樣,把最終FROM換成目標相容的基底映像檔,也不會轉換從另一階段複製來的不相容執行檔。
5. 分開判斷腳本、缺少直譯器與權限
對直接執行的腳本,檢查開頭位元組與直譯器行:#!標頭須指向預期直譯器,該直譯器也必須存在於執行檔案系統。留意標頭之前的異常位元組與Windows風格換行。明確透過shell啟動會改變腳本的執行方式,不能證明原先直接執行的路徑已修復。
保留精確錯誤類別。Linux將無法識別的格式或錯誤架構歸為ENOEXEC;路徑、腳本直譯器或ELF直譯器缺失屬於ENOENT;執行權限遭拒或noexec掛載等權限問題屬於EACCES。因此,看得到檔案也可能因直譯器缺失而失敗。chmod無法修復錯誤CPU架構,加入模擬執行也不會安裝缺少的直譯器。
6. 一次修一個原因,再驗證原路徑
依證據選擇分支:缺少變體就修映像檔選擇或建置輸出;內含二進位檔錯誤就重建或替換該產物;腳本格式錯誤就修標頭或編碼;缺少直譯器就提供所需相容執行環境;權限遭拒就查使用者、檔案模式與掛載政策。清除映像檔不能取代判定故障分支。
模擬執行是刻意執行非原生程式的一種選擇。修改主機層級binfmt註冊前,先確認實際工作節點的支援情況;Docker Desktop與官方BuildKit可能已提供模擬功能。修復後,在可丟棄的非正式環境,以相同預期命令、平台、使用者與相關掛載測試。記錄新digest及具體改變的檢查項目。仍失敗時保留新錯誤,從該失敗層繼續,而非重複同一次重建。
