为什么在 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
作为基础映像
- 将系统库作为映像的一部分进行复制(可能麻烦多于它的价值)
我正在研究 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
作为基础映像 - 将系统库作为映像的一部分进行复制(可能麻烦多于它的价值)