Quarkus Docker容器在ARM平台运行失败:exec格式错误求助
问题根源
你遇到的exec ./application: exec format error是因为Docker镜像中打包的Quarkus原生二进制文件架构与ARM主机不匹配:
- 在GitHub Actions的
ubuntu-latest(amd64架构) runner上,用-Dquarkus.native.container-build=true构建的原生应用是amd64架构的。 - 后续用Docker Buildx构建多平台镜像时,只是把同一个amd64二进制复制到了
linux/arm64镜像中,导致ARM主机无法识别执行该二进制。
解决方案
方案一:多阶段Docker构建(推荐)
将Quarkus原生构建过程嵌入Dockerfile,利用Buildx的多平台构建能力,为每个目标架构单独生成匹配的原生二进制。
修改Dockerfile
# 第一阶段:构建Quarkus原生应用(使用对应架构的Mandrel镜像) FROM quay.io/quarkus/ubi-quarkus-mandrel:23-java17 AS builder WORKDIR /workspace COPY pom.xml . COPY src src # 无需container-build=true,因为已经在对应架构的构建镜像中运行 RUN ./mvnw package -Dnative # 第二阶段:构建轻量运行镜像 FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8 WORKDIR /work/ RUN chown 1001 /work \ && chmod "g+rwX" /work \ && chown 1001:root /work COPY --from=builder --chown=1001:root /workspace/target/*-runner /work/application RUN chmod +x /work/application EXPOSE 8080 USER 1001 ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
简化GitHub工作流
移除提前构建原生应用的阶段,直接在Buildx中完成多平台构建:
push-backend-to-docker-hub: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push backend uses: docker/build-push-action@v5 with: push: true tags: cre8ivemind/creative-mind-backend:latest platforms: linux/amd64,linux/arm64 context: ./backend
方案二:提前构建多架构原生二进制
如果需要保留提前构建的流程,可在GitHub Actions中用QEMU分别构建amd64和arm64的原生二进制,再在Docker构建时根据平台复制对应文件。
修改GitHub工作流的构建阶段
test-and-build-backend: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Java environment uses: actions/setup-java@v3 with: java-version: "17" distribution: "temurin" - name: Set up QEMU uses: docker/setup-qemu-action@v3 # 构建amd64架构原生应用 - name: Build Backend (amd64) run: | cd backend chmod +x mvnw ./mvnw package -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel:23-java17-amd64 mkdir -p target/amd64 mv target/*-runner target/amd64/ # 构建arm64架构原生应用 - name: Build Backend (arm64) run: | cd backend chmod +x mvnw ./mvnw package -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel:23-java17-aarch64 mkdir -p target/arm64 mv target/*-runner target/arm64/ - name: Archive Backend uses: actions/upload-artifact@v3 with: name: backend path: backend/target
修改Dockerfile
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8 WORKDIR /work/ RUN chown 1001 /work \ && chmod "g+rwX" /work \ && chown 1001:root /work # 根据构建平台复制对应架构的原生二进制 COPY --chown=1001:root target/${TARGETPLATFORM#linux/}/*-runner /work/application RUN chmod +x /work/application EXPOSE 8080 USER 1001 ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
更新Docker构建步骤
在Buildx构建时传递平台参数:
- name: Build and push backend uses: docker/build-push-action@v5 with: push: true tags: cre8ivemind/creative-mind-backend:latest platforms: linux/amd64,linux/arm64 context: ./backend build-args: | TARGETPLATFORM=${{ steps.buildx.outputs.platform }}
内容的提问来源于stack exchange,提问作者ihaveaquestion
相关产品推荐
相关产品推荐

