Adding Linux utilities to docker image based on busybox

Viewed 3189

When I try df -h for busybox container I get the following results:

$ docker run -it busybox du -h  
# expected results

What I need is the output of df -b which gives me the following:

$ docker run -it busybox du -b                                                                     
du: invalid option -- b
BusyBox v1.30.0 (2018-12-31 18:16:17 UTC) multi-call binary.

Usage: du [-aHLdclsxhmk] [FILE]...

Summarize disk space used for each FILE and/or directory

    -a  Show file sizes too
    -L  Follow all symlinks
    -H  Follow symlinks on command line
    -d N    Limit output to directories (and files with -a) of depth < N
    -c  Show grand total
    -l  Count sizes many times if hard linked
    -s  Display only a total for each argument
    -x  Skip directories on different filesystems
    -h  Sizes in human readable format (e.g., 1K 243M 2G)
    -m  Sizes in megabytes
    -k  Sizes in kilobytes (default)

As many of the standard utilites are trimmed in busybox image or non-existent, the behaviour is not surprising. As dockerhub's busybox page suggests:

FROM busybox
COPY ./my-static-binary /my-static-binary
CMD ["/my-static-binary"]

So, I created a Dockerfile with the following content trying to copy my Ubuntu 16.04 du binary to the image:

FROM busybox
COPY /usr/bin/du /bin/du
CMD ["/bin/du", "-b"]

But when I try docker build I get the following error:

$ docker build .              
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> 3a093384ac30
Step 2/3 : COPY /usr/bin/du /bin/du
COPY failed: stat /var/lib/docker/tmp/docker-builder362173879/usr/bin/du: no such file or directory

I don't know if it's the right way of adding utilities to such minimal images, but I would appreciate if you let me know the ways that utilities such as (complete) du, curl, etc. could be added given that there is no package manager like apt.

2 Answers

If the just-Busybox Docker base image isn't meeting your needs, you can change your Dockerfile to be based on a more full-featured Linux distribution. FROM ubuntu is very common and includes the GNU versions of the Unix toolset (and their assorted vendor extensions); FROM alpine is also common and is based around Busybox plus a minimal package manager.

Another good answer is to limit yourself to the functionality defined in POSIX.1: du(1) is not required to support a -b option. This will help if you're trying to write Alpine-based images or run on systems that aren't Linux (MacOS being the most prominent present-day example).

You probably will not succeed in copying individual binaries from your host system into a Docker image, path issues aside, because the library environments are likely to be very different. If you run ldd $(which du) on the host, all of the libraries listed there need to be present in the image and at a similar version. The busybox base image probably doesn't even include a libc.so.6, which is a minimum requirement for most dynamically-linked binaries.

The correct answer to your question as it's written is to write a multi-stage Dockerfile that has a first stage with a full C toolchain that builds a static version of GNU Coreutils, and then a second stage that copies it in. That's a lot of work for a tool that's probably not part of the core application you actually want to run.

The COPY is not working because of following restriction:

COPY obeys the following rules:

The path must be inside the context of the build; you cannot COPY ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

You can read more in Dockerfile documentation.

In order to make your busybox image work you should do following:

  1. copy du to directory where your Dockerfile resides: cp /usr/bin/du .
  2. update your Dockerfile:
FROM busybox
COPY du /du
CMD ["du", "-b"]
3. rebuild your image: `docker build .`

According to busybox docker documentation you should put copied binaries directly to the / instead of /bin/.

Related