tiny-server-with-busybox-and-c.md 4.6 KB

Tiny HTTP server docker image based on BusyBox and C

Create a new directory to keep everything organized. I have used port 8081 to keep things different from inside container and out. But you can use any port you wish.

This should create a simple HTTP server for static files. The image should be around ~2mb in size. BusyBox (musl) should take ~1.47mb (smaller than Alpine Linux) and tiny-web-server written in C when built for musl will be around ~75kb. Compare that to a latest nginx image being 126MB when I'm writing this. This would be an overkill for a static server, hence this C based one.

Building the tiny-web-server

tiny-web-server is just excellent for a simple, tiny, static file web server. It is written in C, so it's efficient and the executable is very small (~30kb) and ideal for a small docker image. It is just one file of C code but still does the job wonderfully.

There are no binary releases on the GitHub project, so we'll have to build it ourselves. But not to worry, it's so easy and so short nearly anybody can do it.

From the folder we created for our project, let's clone the repo:

git clone --depth=1 https://github.com/shenfeng/tiny-web-server.git
cd tiny-web-server

Now let's build it. You will need to have gcc plus musl cross compile packages installed, then run:

I was on Void Linux x86_64, so I ran:

sudo xbps-install cross-x86_64-linux-musl

Then, to build the binary:

x86_64-linux-musl-gcc -static -o server tiny.c

As sidenote, if I were to run it on my computer outside of docker image I would do gcc -o server tiny.c. But we're not doing that. BTW, if you run normal executables in the busybox docker, you'll see a standard_init_linux.go:211: exec user process caused "no such file or directory" error. That's why we're building this way. -o is for output. -static is to link the required libraries statically inside the executable. This is to keep it simple and to cause minimal trouble running this inside docker. So this command will output a binary file named server. It will take merely seconds (if not less) to build it and it's so tiny and basic, practically no errors should show up. So easy!

Now let's put that on our main folder and tidy up things:

cd ..
cp tiny-web-server/server ./
# optional: delete the repo folder
rm -rf tiny-web-server

Check the file size. I built it on a Linux x86_64 machine and it was just ~75kb!! Amazing!

But there is one issue with this server -- it does not go to index.html automatically if you go to a directory that has one. Maybe it's a flaw, maybe it's intentional, maybe you can edit the source code to do it exactly that. But I was busy so I didn't try. Just something to let you know.

With Docker Compose

To me, with Docker Compose, it becomes a lot more cleaner and manageable. If you want to do this with Dockerfile, see below.

nano docker-compose.yml

web:
  image: busybox:musl
  volumes:
   - ./server:/bin/server
   - ./www:/www
  ports:
   - "8080:8081"
  command: /bin/server /www 8081

You can easily replace image: busybox:musl with image: alpine and it should still work (because Alpine is musl based). But Alpine is slightly larger than busybox. We're using busybox:musl variant because the default one is based on uClibc and building with it is very complicated (requires learning Buildroot).

You can run tiny-web-server 3 ways:

./server  # this will run the server on 9999 and consider the current directory as webroot
./server www # this will run the server on 9999 and consider the "www" directory as webroot
./server www 8089 # this will run the server on 8089 and consider the "www" directory as webroot

By default tiny-web-server runs on port 9999. So we are specifying 8081 as our port of choice and pointing to www for using our webroot.

Ensure that there is a www directory: mkdir www

Put an index.html file as a test: echo "Your server is working!!" > www/index.html

Now run: docker-compose up \ Open http://localhost:8080 \ Ctrl+C to stop server

With Dockerfile

You can also try this with Dockerfile.

nano Dockerfile

FROM busybox:musl
COPY ./server /bin/
COPY ./www /www
CMD /bin/server /www 8081

Build the image with:

docker build -t tinyc-server .

Verify it's created:

docker images | grep "tinyc-server"

Run it:

docker run -p 8080:8081 --rm -it tinyc-server

Now access your server from: http://localhost:8080