Docker image executing golang executable: exec /usr/local/go/bin/go: exec format error

huangapple go评论79阅读模式
英文:

Docker image executing golang executable: exec /usr/local/go/bin/go: exec format error

问题

我理解我需要指定一个go可执行文件的目标平台,如果它打算在另一台机器上运行。我正在使用搭载 M1 芯片的苹果机器构建一个 Docker 镜像:

Dockerfile

FROM --platform=linux/amd64 golang:alpine AS build

WORKDIR /

ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o .

FROM --platform=linux/amd64 scratch

WORKDIR /app
COPY --from=build /foo /foo

CMD ["./foo"]

这似乎可以工作,因为在构建后检查容器输出:

"Architecture": "amd64",
"Os": "linux"

但是,当我现在使用 docker-compose 在 Linux 服务器上启动镜像时,我收到一个错误:exec /usr/local/go/bin/go: exec format error

docker-compose.yml

foo:
    environment:
      - PORT=${PORT}
    image: docker.io/name/foo
    platform: linux/amd64
    ports:
      - "8000:8000"
    restart: always

我对 Docker 还不太熟悉,所以我猜我在这里漏掉了一些非常明显的东西。

英文:

I understand that I need to specify the target platform of a go executable if it is supposed to run on another machine. I'm building a docker image on an apple machine with the M1 chip:

Dockerfile

FROM --platform=linux/amd64 golang:alpine AS build

WORKDIR /

ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o .

FROM --platform=linux/amd64 scratch

WORKDIR /app
COPY --from=build /foo /foo

CMD ["./foo"]

This appears to work because inspecting the container after build outputs

"Architecture": "amd64",
"Os": "linux"

But when I now start the image on a linux server using docker-compose, I get an error: exec /usr/local/go/bin/go: exec format error

docker-compose.yml

foo:
    environment:
      - PORT=${PORT}
    image: docker.io/name/foo
    platform: linux/amd64
    ports:
      - "8000:8000"
    restart: always

I'm pretty new to docker, so I guess I'm missing something quite obvious here.

答案1

得分: 1

首先,我可以确认您已成功构建了一个amd64二进制文件,所以这不是一个关于go的问题。

如果我在一个amd64的Linux系统上运行您的镜像,我没有遇到您报告的错误。给定以下的docker-compose.yaml文件:

foo:
    environment:
      - PORT=${PORT}
    image: docker.io/chedched/foo
    platform: linux/amd64
    ports:
      - "8000:8000"
    restart: always

当运行docker-compose up时,我看到以下错误信息:

ERROR: for images_foo_1  Cannot start service foo: failed to create shim task:
OCI runtime create failed: runc create failed: unable to start container
process: exec: "./foo": stat ./foo: no such file or directory: unknown

这是因为您设置了WORKDIR /app,这使得app成为您镜像中的当前工作目录,但是您将二进制文件安装为/foo。您需要做以下更改之一:

  • 将您的CMD更改为引用正确的位置:

    CMD ["/foo"]
    

    或者...

  • 将二进制文件安装到/app中:

    COPY --from=build /foo ./foo
    

通过进行上述任何更改,镜像将按预期运行。

英文:

First, I can confirm that you have successfully built an amd64 binary, so this isn't a go question.

If I run your image (on an amd64 linux system), I don't get the same error that you've reported. Given this docker-compose.yaml:

foo:
    environment:
      - PORT=${PORT}
    image: docker.io/chedched/foo
    platform: linux/amd64
    ports:
      - "8000:8000"
    restart: always

When running docker-compose up, I see:

ERROR: for images_foo_1  Cannot start service foo: failed to create shim task:
OCI runtime create failed: runc create failed: unable to start container
process: exec: "./foo": stat ./foo: no such file or directory: unknown

And this happens because you've set WORKDIR /app, which makes app the current working directory in your image, but you've installed your binary as /foo. You need to either:

  • Change your CMD to reference the correct location:

    CMD ["/foo"]
    

    Or...

  • Install the binary in /app:

    COPY --from=build /foo ./foo
    

With either of those changes, the image runs as expected.

huangapple
  • 本文由 发表于 2023年2月22日 08:25:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75527186.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定