A 1 KB Docker Container
blog.quickmediasolutions.com
blog.quickmediasolutions.com
Details: http://thebsdbox.co.uk/in-pursuit-of-a-tinier-binary-er/
Code: https://gist.github.com/thebsdbox/29e395299f89b52214b66269f5...
mov rax,34 ; pause()
syscalltianon/sleeping-beauty latest 2e8193709fa7 6 months ago 129B
https://github.com/tianon/dockerfiles/tree/master/sleeping-b...
> It was created to test how many containers docker can spin up
What was the answer? I'd think on the order of 200-300 on a server with 64 GB of RAM. (Pure guess!)
If you use default docker options, you'll be creating a veth pair per container. You might run into a limit there at around 1024 containers. You also might hit ulimit if your system isn't well configured.
If you use --net=none, you won't hit that issue, and you'll probably be able to manage quite a few
The resource usage ends up being roughly 4 bytes rss for the executable in the container and around 3.5MB for the "containerd-shim" go binary that parents the container.
"containerd" and "dockerd" both probably have a little extra resource usage per container they're managing, but I'd guess that's on the order of about 200KB per at most.
The next big limit you'll hit is the process/pid limit (/proc/sys/kernel/pid_max) which defaults to 32k.
Fortunately, due to the memory overhead of a bit under 4MB, you probably won't get there on your 64GB of ram server and might cap out at around 15k containers total.
Experimentally, my linux laptop (running docker 17.06) is able to run 1100 copies of that sleeping-beuaty container using almost exactly 2GB RSS additional memory and no noticeable additional cpu
This is even better than I calculated above, possibly due to shared memory for containerd-shim. I'm not investigating further.
The first part of my post is speculating, the second part I ran an arbitrary number and observed resource usage to allow extrapolation, but didn't hit a limit.
General good practice for sysadmins is to affine CPU cores/threads so that you don't end up flushing the CPU cache too aggressively and you don't split your VM's over NUMA zones because memory locality is important.
https://github.com/docker-library/hello-world/blob/master/he...
I always thought this was a bit misleading. A "hello world" container is 1 kB, but the bare minimum container that does something useful in practice is rarely less than 100 MB in size.
One example i use is an agent i deploy to kubernetes clusters to do some security scanning. The scripts are ruby and the image clocks in at 9MB compressed https://hub.docker.com/r/raesene/kaa-agent/tags/
If you're into go, it's not too hard to get very small (<5mb) shippables by statically compiling against musl and using upx. Here's a somewhat scrubbed Dockerfile for a gRPC/rest service I use at work: https://gist.github.com/jbergstroem/680cb7db6f90319dcd7666f3...
I’ve made containers using code written in most common programming languages (python/go/ruby/c/rust/heck even PHP/etc) which were easily under 100mb, most significantly less. If your containers are frequently >100mb, I say you’re either using the JVM or are doing it wrong!
Nomad supports raw executables to be downloaded and scheduled, which is nice(https://nomadproject.io) but then again, kubernetes seems miles ahead in what it supports (autoscaling, volume claims, RBAC etc)
Otherwise, more traditional means of managing your services can be employed. I've got a lot of leverage out of systemd myself. Which by the way, supports all the features of a proper container runtime. You can namespace your executable, Chroot it, limit what devices it can access, etc, which is kinda awesome. Check out `man systemd.exec` and `man systemd.resource-control`
Kubernetes also supports extensions like the Third Party Resource or their successor, Custom Resource Definitions. KubeVirt[1] is an example of extending resources to include VMs
[0] http://blog.kubernetes.io/2016/12/container-runtime-interfac...
And in most real world cases, you will still need at least libc and ca-certificates.
However there is a great lesson to take from this: you can create single-binary but really useful containers for just a few MBs, which is nothing in practice for a usual sized server, an a lot more lightweight than usual containers based off Alpine or Ubuntu.
In fact I run my static websites using that: a small 8-ish MB statically compiled web server "written" (it's really just library glue) in Go.
It just runs a tight loop that consumes an entire core.
Replace -d with -D for macOS
Another useful technique, which has been recently introduced, is Multi-Stage Builds https://docs.docker.com/engine/userguide/eng-image/multistag... . This lets you avoid putting tools needed for compilation into the final image.
http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...
736B may seem tiny to most people, but if you're working in Asm that's a lot --- there's plenty of interesting things (beyond "call the OS a few times") the demoscene has done with smaller binaries; here's an assortment of 512B ones:
The whole idea is to compile a go program and put it into a docker container and have it listening to the network for a single HTTP endpoint.
It is interesting because an useful images come to be less than 6MB :)
Link to the project: https://github.com/siscia/effe-tool
eg. https://hub.docker.com/r/0xff/asmttpd/
7KB web server container.
[0]: https://github.com/kubernetes/kubernetes/tree/master/build/p...