Prawn Hongs
Prawn Hongs

Reputation: 451

How to build a docker build file that can run my c++ program in busybox?

I am trying to play and learn docker usage in embedded world. I am using busybox docker image as a start and I am trying to copy my C++ program binary on to the docker container. However, I see that I am unable to execute the binary in the busy box. I am not sure what am I missing. Is busy box docker usage is something like this?

Here is what I have tried so far - the

Dockerfile

FROM busybox:1.30
COPY ./test4.out /home/
CMD  /home/test4.out

Now, here is my c++ code.

#include <iostream>

using namespace std;

int main()
{

  return 120;
}

I have compiled this code in my host machine-

#gcc test4.cpp  -o test4.out

Build my docker

docker build -t abc/busybox-smarter:1.0 .

docker build -t abc/busybox-smarter:1.0 .
Sending build context to Docker daemon  12.29kB
Step 1/3 : FROM busybox:1.30
 ---> af2f74c517aa
Step 2/3 : COPY ./test4.out /home/
 ---> Using cache
 ---> 1d6fe02933c1
Step 3/3 : CMD  /home/test4.out
 ---> Using cache
 ---> dd590ef4059d
Successfully built dd590ef4059d
Successfully tagged abc/busybox-smarter:1.0

Now, I am running this image.

docker run --rm -ti abc/busybox-smarter:1.0 /bin/sh

/home # ./test4.out 
/bin/sh: ./test4.out: not found

Upvotes: 2

Views: 2113

Answers (1)

larsks
larsks

Reputation: 312858

The busybox image contains a minimal collection of statically compiled binaries (most of which are really just hardlinks to busybox). The output of your gcc command, on the other hand, is a dynamically linked executable:

$ g++ -o test4.out test4.cpp
$ file test4.out
test4.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=9c3a99f3baa5f699f4e32fa65acc58ac8ddc099c, not stripped

In order to execute, it requires the appropriate dynamic loader (typically something like /lib64/ld-linux-x86-64.so.2).

This doesn't exist in the busybox image, which leads to the "not found" error.

In addition to the dynamic loader, your code has a few additional shared library dependencies:

$ ldd prog
        linux-vdso.so.1 (0x00007fff01dbb000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f566279e000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f566240a000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f56621f2000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f5661e34000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5662b30000)

You would need to make all those shared libraries available inside the image for your code to run.

You can try to statically compile your code. You will first need to arrange to have the static versions of any required libraries on your system. On my Fedora 28 environment, this meant I first had to run:

yum -y install libstdc++-static glibc-static

And then I was able to generate a static version of the binary:

$ g++ --static -o test4.out test4.cpp
$ file test4.out
test4.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=d0f3b446020e1b067ededb59ec491bff9634f550, not stripped

I can run this image in a busybox container without a problem.

WARNING! There are some functions (typically those dealing with hostname resolution and users/groups) that require dynamic shared libraries at runtime even when compiled with --static.

Upvotes: 4

Related Questions