3

The docker documentation says that you can build this minimal image:

FROM scratch
ADD hello /
CMD ["/hello"]

Presumably the way this works is that the CMD step is using the default shell (that is, bin/sh, per https://stackoverflow.com/a/21564990/10900852) to run the hello executable.

But if SCRATCH is really entirely empty, where is bin/sh coming from? Why does my image contain a shell?

sherz1
  • 89
  • 1
  • 6

1 Answers1

9

A container built from scratch does NOT have anything inside at the beginning, so your image contains no /bin/sh.

However, there are two formats of CMD which matters here:

CMD ["/hello"]
CMD /hello

The first format specifies a full command and is called directly via execve(2). The actual process executed is as exactly as ["/hello"] (i.e. argc == 1)

The second format specifies a "entrypoint parameter" and is passed as a single argument to entrypoint, so Docker will attempt to run ["/bin/sh", "-c", "/hello"] with argc == 3 and fail.

You can replace the CMD line with CMD /hello and observe it for yourself.

iBug
  • 35,554
  • 7
  • 89
  • 134
  • That makes a lot of sense! So then a basic followup - why would I want to distribute my binary as a container, and not just as a binary itself? Is it for interoperability between systems, that anyone can pull my image and run it with docker if it's a container, but a binary is compiled against a specific os/arch? – sherz1 May 13 '21 at 04:21
  • @sherz1 If your binary is statically linked, then it makes little difference in distributing it alone vs. in a container. However, wrapping it up in a container won't help if the architecture is different. You still won't run an ARM binary on a x86 machine, without special translation help. – iBug May 13 '21 at 04:28
  • @sherz1 But yeah, if it's dynamically linked or requires extra libraries, containers can ensure the execution environment stays consistent, so you don't have to worry about wrong library versions of missing libraries etc. – iBug May 13 '21 at 04:29