3

I'm trying to understand why can't I run java inside docker container without having a base OS image.
I tried the next basic dockerfile:

FROM scratch

ADD openjdk-11.0.2_linux-x64_bin.tar.gz /java

CMD ["/java/jdk-11.0.2/bin/java", "-version" ]

And got the following error:

standard_init_linux.go:207: exec user process caused "no such file or directory"

In my understanding that's probably has something to do with unmet dependencies, but I still don't understand why I need all the user-space file system that comes with base images just to run a binary executable. aren't they supposed to run natively? what's the difference between binary that's able to run standalone and one that doesn't?

In addition I'm interested to know what is that file standard_init_linux.go? does the linux kernel contains go code?

I've found some resources about base images (below), but they still doesn't provide direct answer for my question.

Resources

matanper
  • 881
  • 8
  • 24
  • well in containers base os image isn't a full OS. the container still using the kernel of host machine. for example I can compile go code to run on `scratch` image – matanper May 10 '19 at 19:03
  • 1
    standard_init_linux.go is probably a part of docker - https://github.com/docker/libcontainer/blob/master/standard_init_linux.go – battlmonstr May 10 '19 at 19:04
  • Similar question: https://stackoverflow.com/questions/55416831/create-docker-image-for-jre-from-scratch – battlmonstr May 10 '19 at 19:08
  • @Robert I did with another base image, but I don't know how to this in `scratch` since I don't have shell – matanper May 10 '19 at 19:14
  • 1
    Depending on your use case, maybe using Google's "distroless" java base image would be an option instead of building your own: https://github.com/GoogleContainerTools/distroless – JamesJJ May 10 '19 at 19:20
  • @matanper you can list the contents with: `docker container export $(docker container create IMAGE_NAME_OR_ID) | tar --list --verbose` – Robert May 10 '19 at 19:26

3 Answers3

5

The binary has shared library dependencies. If those dependencies aren't in the system, it won't run.

As you said, it's hard to inspect the image directly, but you can take a look at the executable on your host system. Here's what it looks like on mine:

$ ldd java/jdk-11.0.2/bin/java
    linux-vdso.so.1 (0x00007ffc16fac000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fd839c97000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd839a78000)
    libjli.so => /home/jkugelman/from-scratch-java/java/jdk-11.0.2/bin/../lib/jli/libjli.so (0x00007fd839867000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd839663000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd839272000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fd839eb4000)

Mounting /lib and /lib64 gets it to run:

$ docker run --rm -it -v /lib:/lib -v /lib64:/lib64 from-scratch-java
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
1

Shared libraries.

Executables that aren't statically linked need a linker, a loader, and shared libraries (like the standard C library) that they link against. That's provided by your OS image.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • If it doesn't exec out into other utilities (like a shell), yes, it should. If you want to track exactly what it's trying to do, I'd strongly suggest using [`sysdig`](https://sysdig.com/). – Charles Duffy May 10 '19 at 19:19
  • There may also be references to configuration files like `/etc/resolv.conf` used, but those won't cause an `execve()` failure on initial invocation; it's really just the linker/loader, its own dependencies (`/etc/ld.so.conf` &c) and the shared libraries that will cause a failure that early. – Charles Duffy May 10 '19 at 19:20
-2

Java/JVM is really just another executable program like 'apache' or 'top'. like all programs it needs an operating system host to manage the hardware and provide standardized interfaces. The binary code of Java is compiled against specific OS's and Kernels.

More fundamentally, I am curious if Docker container would run without a base OS image. The container should use the host Kernel, but it should still require a base OS image on top of the kernel.