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

Time:03-24

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

CodePudding user response:

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)
  • Related