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.
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.
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
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