为什么在 Docker 图像中无法识别某种二进制文件?

Why is a type of binary not recognized in a Docker image?

我正在研究 Docker 图像构建并从头开始制作了一个图像,其中有两个二进制文件都休眠一小时:

$ cat Dockerfile
FROM scratch
COPY c-sleeper /
COPY go-sleeper /

问题是:为什么 运行ning go-sleeper 成功而 c-sleeper 失败?

$ docker run --rm sleepers /go-sleeper
// (not printing anything as expected, just sleeping)

$ docker run --rm sleepers /c-sleeper
exec /c-sleeper: no such file or directory

c-sleeper 由

构建
#include <unistd.h>

int main() {
  sleep(60*60);
  return 0;
}

使用

$ gcc --version
gcc (GCC) 11.2.0
$ gcc source.c -o c-sleeper

睡衣是用

建造的
package main

import "time"

func main() {
  time.Sleep(time.Hour)
}

使用

$ go version
go version go1.17.8 linux/amd64
$ GOOS=linux go build -o sleep main.go

两个二进制文件在主文件系统中执行良好,即当不在容器中时 运行。因此,我不确定我是否应该将这个问题标记为关于使用 GCC 进行编译或使用 Docker 图像进行操作。

$ docker --version
Docker version 20.10.12, build e91ed5707e

您的 C 应用程序是动态 linked,这意味着它不能 运行 没有其他库。因为您的应用程序非常简单,这可能只意味着 libc,但更复杂将意味着更多的库。

您有几个选项,按复杂程度大致排序:

  • 静态 link 您的应用程序 (gcc c-sleeper.c -static -o c-sleeper);这将需要你需要的任何库的静态版本
  • 如果您需要系统库,请不要使用 scratch 作为基础映像
  • 将系统库作为映像的一部分进行复制(可能麻烦多于它的价值)