Docker中无法运行macOS(Mach-O)可执行文件:Exec format error求助
各位技术同仁好,我在使用Docker时遇到如下错误,恳请帮忙排查:
> /opt/logs/supervisord-my_application.log <
Cannot run macOS (Mach-O) executable in Docker: Exec format error
Cannot run macOS (Mach-O) executable in Docker: Exec format error
Cannot run macOS (Mach-O) executable in Docker: Exec format error
Cannot run macOS (Mach-O) executable in Docker: Exec format error
我的docker-compose文件
version: "3.8" services: app-service: image: "sha256:tag" platform: linux/amd64 container_name: my-app-service environment: - ENV=qa - CLOUD_PROFILE=prod-ecs-service-dc - GOCOVERDIR=/opt/coverage - DB_HOST=mysql - DB_PORT=3306 - DB_USER=root - DB_PASSWORD=example ulimits: nproc: 100000 healthcheck: test: [ "CMD-SHELL", "curl -f http://localhost:80/my-app-service-ping || exit 1" ] ports: - "8082:8081" volumes: - /opt/logs:/opt/logs - /root/.cloud/:/root/.cloud networks: - external depends_on: mysql: condition: service_healthy restart: on-failure
我的Dockerfile
# syntax=docker/dockerfile:1 FROM your-registry-url/base-images:golang-1.20.5-alpine3.18-gh AS builder ENV DEBIAN_FRONTEND=noninteractive ENV GO111MODULE=on \ GOPROXY=https://proxy.golang.org,http://your-proxy-server/repository/go-prod-github-athens/,direct \ GOSUMDB=off \ PATH=/usr/local/go/bin:${PATH} \ GOBIN=/usr/local/bin RUN \ apk update && \ apk add --no-cache \ gcc \ bash \ musl-dev && \ apk add git && \ apk add make && \ apk add cyrus-sasl-dev && \ apk add python3 && \ apk add g++ && \ apk add pkgconfig && \ apk add tzdata && \ apk add g++ && \ apk add krb5-dev g++ #For golang applications RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2 WORKDIR /usr/local/app/src/myapplication COPY go.mod . COPY go.sum . COPY ./ /usr/local/app/src/myapplication RUN make buildApplication && \ chmod +x /usr/local/app/src/myapplication/deploy.sh FROM your-registry-url/base-images:alpine3.18 as Runner RUN apk add --update supervisor && \ apk add --no-cache supervisor bash && \ mkdir -p /opt/logs && \ apk add git && \ apk add tzdata RUN apk update && apk add --no-cache chromium chromium-chromedriver COPY --from=builder /usr/local/app/src/myapplication/bin/myapplication \ /usr/local/app/src/myapplication/bin/myapplication COPY --from=builder /usr/lib/pkgconfig /usr/lib/pkgconfig COPY --from=builder /lib /usr/lib COPY --from=builder /lib64 /usr/lib RUN ln -s /usr/lib/libc.musl-x86_64.so.1 WORKDIR /usr/local/app/src/myapplication COPY ./ /usr/local/app/src/myapplication EXPOSE 80 # supervisor COPY dockerconfig/supervisord /etc/rc.d/init.d/ COPY dockerconfig/supervisord_prod.conf /etc/supervisord_prod.conf COPY dockerconfig/services_prod.conf /etc/supervisord.d/services_prod.conf COPY dockerconfig/supervisord_prodpp.conf /etc/supervisord_prodpp.conf COPY dockerconfig/services_prodpp.conf /etc/supervisord.d/services_prodpp.conf COPY dockerconfig/supervisord_async.conf /etc/supervisord_async.conf COPY dockerconfig/services_async.conf /etc/supervisord.d/services_async.conf COPY dockerconfig/supervisord_cron.conf /etc/supervisord_cron.conf COPY dockerconfig/services_cron.conf /etc/supervisord.d/services_cron.conf COPY dockerconfig/supervisord_qa.conf /etc/supervisord_qa.conf RUN chmod 777 /usr/local/app/src/myapplication/bin/myapplication RUN chmod 755 /etc/rc.d/init.d/supervisord ENV ENV="prod" RUN echo "Service Name: ${ENV}" RUN echo "/etc/supervisord_${ENV}.conf" CMD /usr/bin/supervisord -n -c /etc/supervisord_${ENV}.conf
问题分析与修复方案
核心原因
错误明确指向容器内运行的是macOS平台的Mach-O格式可执行文件,而Docker容器基于Linux系统,仅支持ELF格式二进制,导致执行失败。大概率是构建过程中生成的二进制文件目标平台不对,或是本地编译的Mach-O文件被意外复制到镜像中。
具体修复步骤
强制Go交叉编译为Linux平台
修改make buildApplication对应的编译命令,添加Linux/amd64的目标参数:GOOS=linux GOARCH=amd64 go build -o bin/myapplication ./main.go确保在builder阶段的Linux容器内生成ELF格式的二进制,而非本地macOS环境的Mach-O文件。
添加.dockerignore避免本地文件干扰
在项目根目录创建.dockerignore文件,忽略本地编译生成的bin/目录:bin/防止Dockerfile中
COPY ./ ...命令把本地的Mach-O文件复制到镜像中,覆盖builder阶段生成的正确二进制。验证编译产物格式
在builder阶段编译完成后添加验证步骤,确认生成的是Linux兼容的二进制:RUN file /usr/local/app/src/myapplication/bin/myapplication正常输出应包含
ELF 64-bit LSB executable,若显示Mach-O则说明编译参数仍有问题。检查supervisor配置路径
确认supervisord配置中指向的二进制路径是容器内的/usr/local/app/src/myapplication/bin/myapplication,而非主机挂载的文件(当前volumes未挂载bin目录,此问题概率较低,但需确认)。
内容的提问来源于stack exchange,提问作者recovery

