[Haskell-cafe] Static executables in minimal Docker containers

Michael Snoyman michael at snoyman.com
Sat Apr 18 18:51:19 UTC 2015


The /lib/ version of the file was necessary for statically linked
executables I believe. It's arguably better to just remove it and tell
people "don't do static executables" I suppose, given that they're clearly
not *actually* static in reality ;)

On Sat, Apr 18, 2015, 12:51 PM Vo Minh Thu <noteed at gmail.com> wrote:

> Michael, thanks for solving this !
>
> I wonder how you came up with the need for /lib/ld-linux-x86-64.so.2.
> I have needed only /lib64/ld-linux-x86-64.so.2 (which you have too),
> so maybe you added it by mistake.
>
> B.t.w, if you don't want to use a Dockerfile, you can do this:
>
>     > tar -C rootfs -c . | docker import - tiny
>
> where rootfs is your repository.
>
> 2015-04-14 10:43 GMT+02:00 Michael Snoyman <michael at snoyman.com>:
> > Trac ticket created:
> https://ghc.haskell.org/trac/ghc/ticket/10298#ticket
> >
> > I've also put together a Docker image called snoyberg/haskell-scratch
> > (source at https://github.com/snoyberg/haskell-scratch), which seems to
> be
> > working for me. Here's a minimal test I've put together which seems to be
> > succeeding (note that I've also tried some real life programs):
> >
> > #!/bin/bash
> >
> > set -e
> > set -x
> >
> > cat > tiny.hs <<EOF
> > main :: IO ()
> > main = putStrLn "Hello from a tiny Docker image"
> > EOF
> >
> > ghc tiny.hs
> > strip tiny
> >
> > cat > Dockerfile <<EOF
> > FROM snoyberg/haskell-scratch
> > ADD tiny /tiny
> > CMD ["/tiny"]
> > EOF
> >
> > docker build -t tiny .
> > docker run --rm tiny
> >
> >
> > On Tue, Apr 14, 2015 at 9:52 AM Michael Snoyman <michael at snoyman.com>
> wrote:
> >>
> >> Actually, I seem to have found the problem:
> >>
> >> open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) =
> -1
> >> ENOENT (No such file or directory)
> >> open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules",
> O_RDONLY|O_CLOEXEC)
> >> = -1 ENOENT (No such file or directory)
> >>
> >> I found that I needed to copy over the following files to make my
> program
> >> complete:
> >>
> >> /usr/lib/x86_64-linux-gnu/gconv/gconv-modules
> >> /usr/lib/x86_64-linux-gnu/gconv/UTF-32.so
> >>
> >> Once I did that, I could get the executable to run in the chroot.
> However,
> >> even running the statically linked executable still required most of the
> >> shared libraries to be present inside the chroot. So it seems that:
> >>
> >> * We can come up with a list of a few files that need to be present
> inside
> >> a Docker image to provide for minimal GHC-compiled executables
> >> * There's a bug in the RTS that results in an infinite loop
> >>
> >> I'm going to try to put together a semi-robust solution for the first
> >> problem, and I'll report the RTS issue on Trac.
> >>
> >> On Tue, Apr 14, 2015 at 9:25 AM Michael Snoyman <michael at snoyman.com>
> >> wrote:
> >>>
> >>> I have a bit more information about this. In particular: I'm able to
> >>> reproduce this using chroot (no Docker required), and it's reproducing
> with
> >>> a dynamically linked executable too. Steps I used to reproduce:
> >>>
> >>> 1. Write a minimal "foo.hs" containing `main = putStrLn "Hello World"`
> >>> 2. Compile that executable and put it in an empty directory
> >>> 3. Run `ldd` on it and copy all necessary libraries inside that
> directory
> >>> 4. Run `sudo strace -o log.txt . /foo`
> >>>
> >>> I've uploaded the logs to:
> >>>
> >>> https://gist.github.com/snoyberg/095efb17e36acc1d6360
> >>>
> >>> Note that, due to size of the output, I killed the process just a few
> >>> seconds after starting it, but when I let the output run much longer, I
> >>> didn't see any difference in the results. I'll continue poking at this
> a
> >>> bit, but most likely I'll open a GHC Trac ticket about it later today.
> >>>
> >>> On Tue, Apr 14, 2015 at 12:39 AM Albert Y. C. Lai <trebla at vex.net>
> wrote:
> >>>>
> >>>> I wonder whether you already know the following, and whether it is
> >>>> relevant to begin with. (Plus, my knowledge is fairly sketchy.)
> >>>>
> >>>> Even though you statically link glibc, its code will, at run time,
> >>>> dlopen a certain part of glibc.
> >>>>
> >>>> Why: To provide a really uniform abstraction layer over user account
> >>>> queries, e.g., man 3 getpwnam, regardless of whether the accounts are
> >>>> from /etc/passwd, LDAP, or whatever.
> >>>>
> >>>> Therefore, during run time, glibc first reads some config files of the
> >>>> host to see what kind of user account database the host uses. If it's
> >>>> /etc/passwd, then dlopen the implementation of getpwnam and friends
> for
> >>>> /etc/passwd; else, if it's LDAP, then dlopen the implementation of
> >>>> getpwnam and friends for LDAP; etc etc.
> >>>>
> >>>> So that later when you call getpwnam, it will happen to "do the right
> >>>> thing".
> >>>>
> >>>> This demands the required *.so files to be accessible during run time.
> >>>> Moreoever, if you statically link glibc, this also demands the
> required
> >>>> *.so files to version-match the glibc you statically link.
> >>>>
> >>>> (It is the main reason why most people give up on statically linking
> >>>> glibc.)
> >>>> _______________________________________________
> >>>> Haskell-Cafe mailing list
> >>>> Haskell-Cafe at haskell.org
> >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> >
> >
> > _______________________________________________
> > Haskell-Cafe mailing list
> > Haskell-Cafe at haskell.org
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20150418/cdf762aa/attachment.html>


More information about the Haskell-Cafe mailing list