Issue
I was looking into Docker image building and made an image from scratch that has two binaries that both sleep for one hour:
$ cat Dockerfile
FROM scratch
COPY c-sleeper /
COPY go-sleeper /
Question is: Why does running the go-sleeper
succeed and c-sleeper
fail?
$ 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
The c-sleeper is built from
#include <unistd.h>
int main() {
sleep(60*60);
return 0;
}
using
$ gcc --version
gcc (GCC) 11.2.0
$ gcc source.c -o c-sleeper
and the go-sleeper is built from
package main
import "time"
func main() {
time.Sleep(time.Hour)
}
using
$ go version
go version go1.17.8 linux/amd64
$ GOOS=linux go build -o sleep main.go
Both binaries execute fine in the main file system, i.e. when not run within a container. Hence I'm not sure whether I should tag this question to be about compiling with GCC or doing stuff with Docker images.
$ docker --version
Docker version 20.10.12, build e91ed5707e
Solution
Your C application is dynamically linked, which means it can't run without other libraries. Because your application is so simple, this probably just means libc, but more complexity will mean more libraries.
You have a couple options, in rough order of complexity:
- statically link your application (
gcc c-sleeper.c -static -o c-sleeper
); this will require having static versions of whatever libraries you need - don't use
scratch
as your base image if you need system libraries - copy the system libraries as part of your image (probably more trouble than it's worth)
Answered By - Stephen Newell Answer Checked By - Mildred Charles (WPSolving Admin)