[Haskell-cafe] Static executables in minimal Docker containers

Michael Snoyman michael at snoyman.com
Tue Apr 14 08:43:13 UTC 2015


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
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20150414/f7a40899/attachment-0001.html>


More information about the Haskell-Cafe mailing list