docker-library / busybox

Docker Official Image packaging for Busybox

Home Page:http://busybox.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

nc: bad port spec 'local:/...'

lump opened this issue · comments

I want to have an init script in my tiny Busybox container check to make sure a socket like /dev/log both exists and that there is something listening to it before I start any processes that depend on Syslog inside the container or use the logger command. The problem is, it the official Busybox images don't seem to have any command-line tool that can check the availability of a local Unix socket.

/ # nc -u -z local:/dev/log
nc: bad port spec 'local:/dev/log'

This problem was solved over a decade ago in this old thread:

http://lists.busybox.net/pipermail/busybox/2009-April/069068.html

The problem is that the official busybox image doesn't seem to turn this feature on, even though this may be something that could be needed for some kinds of container logistics. I believe this feature is required for containers that want to run Busybox's syslogd in from something that doesn't guarantee startup order, like init.

I can understand if this adds too much bloat, because Busybox image is so pleasantly small. But please consider turning on FEATURE_UNIX_LOCAL=y in the official Busybox image to allow a container to check a local Unix socket like /dev/log using the nc built-in.

For what it's worth, the official Alpine image does turn this feature on. My beef is that at this point I don't need any of the extras that Alpine has except for this, so I could be using a 1.35MB Busybox image instead of a 8.24MB Alpine image (because I have to add busybox-extras to Alpine).

Unfortunately, we try to keep our enabled options pretty minimal and stick to the BusyBox upstream defaults (since they don't have anything else that resembles "official recommendations" for options to enable/disable in a generic install, and we don't really want to be the arbiters of which configuration options "make the cut" so to speak 😅). Any idea why they don't enable this by default? Does it change the size, complexity, or attack surface significantly or something?

I understand why we should stick to upstream defaults for everything we can. That is, except for the specific things that the official Docker image should probably include. There are a few other features that this build turns on that upstream does not. I believe that this feature qualifies. I think it hasn't been turned on yet just because no one has thought about turning it on.

In this case, I believe that allowing nc (the only Busybox socket command) to connect to a local socket is something that a Busybox Docker container may need to do. Frankly, I'm surprised I'm the first to care enough to say something about it before switching to a different solution. People probably simply switch to Alpine because while it might be 4 times bigger than Busybox, it's still 14 times smaller than debian-slim.

I checked out the lastest from the dist-amd64 branch. Moved over the upstream binary. Built it vanilla.

$ git branch
* dist-amd64
  master
$ mv stable/uclibc/busybox.tar.xz stable/uclibc/busybox-upstream.tar.xz
$ ./build.sh
$ mv stable/uclibc/busybox.tar.xz stable/uclibc/busybox-vanilla.tar.xz

Then I added CONFIG_FEATURE_UNIX_LOCAL=y to setConfs in stable/uclibc/Dockerfile.builder and built it again.

$ git diff stable/uclibc/Dockerfile.builder
diff --git a/stable/uclibc/Dockerfile.builder b/stable/uclibc/Dockerfile.builder
index 452a96d..d4dab1c 100644
--- a/stable/uclibc/Dockerfile.builder
+++ b/stable/uclibc/Dockerfile.builder
@@ -224,6 +224,7 @@ RUN set -eux; \
                CONFIG_AR=y \
                CONFIG_FEATURE_AR_CREATE=y \
                CONFIG_FEATURE_AR_LONG_FILENAMES=y \
+               CONFIG_FEATURE_UNIX_LOCAL=y \
 # CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input)
                CONFIG_LAST_SUPPORTED_WCHAR=0 \
                CONFIG_STATIC=y \

After that, these are the differences in busybox xz size. (Interestingly, my binary was smaller than the upstream, which is why I did a vanilla build first for a control).

$ ls -al stable/uclibc/*.xz ls -al stable/uclibc/*.xz
-rw-r--r-- 1 troy troy 645992 Aug 30 14:07 stable/uclibc/busybox.tar.xz
-rw-r--r-- 1 troy troy 646212 Aug 30 12:26 stable/uclibc/busybox-upstream.tar.xz
-rw-r--r-- 1 troy troy 645964 Aug 30 13:40 stable/uclibc/busybox-vanilla.tar.xz

So, according to this test, it is only 28 more (compressed) bytes to turn this on. That's just a margin of error to me. Inside the container, the busybox binary ended up being the same size.

My test image I just built: 1157408

$ docker run --rm -it busybox:stable-uclibc-test /bin/sh
/ # ls -al /bin/busybox 
-rwxr-xr-x  401 root     root       1157408 Aug 30 20:05 /bin/busybox
/ # ls /dev/log
ls: /dev/log: No such file or directory
/ # syslogd
/ # Aug 30 20:35:33 bf7e6e69c00d syslog.info syslogd started: BusyBox v1.34.1
ls /dev/log
/dev/log
/ # nc -u -z local:/dev/log
/ # echo $?
0
/ # exit

Official Image: 1157408

$ docker run --rm -it busybox:1.34.1-uclibc /bin/sh
/ # ls -al /bin/busybox 
-rwxr-xr-x  401 root     root       1157408 Jul 29 01:32 /bin/busybox
/ # ls /dev/log
ls: /dev/log: No such file or directory
/ # syslogd
/ # Aug 30 20:36:35 2efa5163f891 syslog.info syslogd started: BusyBox v1.34.1
ls /dev/log
/dev/log
/ # nc -u -z local:/dev/log
nc: bad port spec 'local:/dev/log'
/ # echo $?
1
/ # exit

Since the binary is the same size, there's no reason not to turn this on in my opinion. I can submit a pull request if that's what's needed to get a change on the horizon.

That is, except for the specific things that the official Docker image should probably include.

This is the part that causes me pause -- "should" according to whom? 😇

More concretely, how do we make this an objective determination so that we don't next week get a request for CONFIG_FOO_BAR also because it "should" be there as well?

This is the part that causes me pause -- "should" according to whom? innocent

It is according to me. I wrote that. I created this ticket. It is according to my lived experience. I used that word you quote, though I also qualified "should" with "probably," which means presumption. I have used many uncertain words in my earlier suggestions on purpose because I am not an authority on what this project should actually decide to do.

It is obvious that I have no authority here. I, as an end-user, submitted this ticket about my real-world experience trying to use the Busybox image in practice and then discovering that I cannot, because it does not have one of the most basic Unix features that I need in a Docker image. Busybox is a monolith binary that does not allow ex-post-facto augmentation, so this change must be done in the official image. It is that, or I have to make my own image from scratch. I genuinely believed that other people out there could use this feature, so I posted this ticket. That is all this is.

how do we make this an objective determination so that we don't next week get a request for CONFIG_FOO_BAR also because it "should" be there as well?

How to make an objective determination is up to this project's leaders to decide, not me. I am a mere user who noticed this lack and discrepancy and submitted a ticket. If the leaders of this project cannot decide, then I've got nothing.

I am not here to argue about what this project should or shouldn't do. I am only here to make an honest feature suggestion from personal experience to any leaders of this project to accept or reject in their next meeting. In my opinion, this Docker image needs this flag because I definitely need it to implement socket dependencies within Busybox's init inside my containers.

If there are any Busybox features that "should probably" be turned on that cause no cost at all, then, seriously, why not turn them on? Especially for a Docker image that is supposed to serve everyone in the world and cannot be augmented (with a package manager)? Why fear a tiny change that helps this project solve a decade-old problem at no cost? How many other requests to turn on Busybox compile flags like this does this docker-library project have in the backlog? I don't see any open issues listed.

So, this is just a cordial and respectful suggestion. This is not a dispute. I already changed my container solution to use the Alpine image instead, so I have no investment here anymore, anyway. But I will gladly come back to the Busybox image if you guys reconsider.