I’ve been in the IT industry for quite along time now. In fact, if you count from when I first started working as a programmer during my degree, it’s a little over 34 years. During that time I’ve seen quite a few changes, one of which is how much space it takes to install an operating system.
I started my career working on UNIX, originally BSD 4.2 and then, when I moved to AT&T, System V. The thing about these versions is they weren’t very big, literally only taking a few megabytes to install. I can remember installing my operating system using a handful of 1.44 Mb floppy disks. The first PC I owned had a hard drive that was only 240 Mb (no, really). Scroll forward to today, and a quick look at the Ubuntu website shows that to install this version of Linux the recommended minimum free disk space is 25Gb. Yes, 25 Gigabytes!
One of the other thing that has changed a lot, certainly more recently, is the way we develop server-side software. Gone are the days of monolithic applications to be replaced by numerous microservices all orchestrated using something like Kubernetes.
This is great, as it provides a more flexible approach where services can be developed independently of one another. Developers with domain knowledge of specific parts can focus on those delivering to a well-defined interface.
The use of containers has also brought considerable simplification to the deployment of services, especially in the heterogeneous environment that is the cloud.
However, this is where things start to get a little more complicated. Containers using platforms like Docker use images that contain, in essence, a complete operating system image for each service. This is not quite as bad as it sounds since Docker images can be shared amongst multiple services running on the same machine. The issue of size is one that still needs to be considered, especially for when deploying to the cloud since you don’t want to have to copy tens of gigabytes of data just to get a simple web service running.
To address this requirement, there is a very useful version of Linux called Alpine. This is built around two complementary technologies, designed for minimal install sizes:
- The Musl (pronounced Mussel, hence the reference to moluscs in the title of the post) libc implementation. The standard libc is required for pretty much every application.
- BusyBox, which is a set of tiny versions of common UNIX commands
When combined you can run something like this:
$ docker pull alpine ... $ docker -i -t alpine /bin/sh / # du -sh . 4.7M . / # ls -l /lib/ld-musl-x86_64.so.1 -rwxr-xr-x 1 root root 584168 Jun 19 07:48ld-musl-x86_64.so.1
As you can see, the whole Linux filesystem is less than 5 Mb, and the Musl libc is just over 580 Kb.
Now we’re back to the good old days of operating system sizes. Of course, it’s important to remember that this is a very minimal implementation, so you probably need to add some other utilities.
How about Java applications? Well, because this is Alpine Linux and the Musl C library you need a specific version of the JDK. That’s where Azul can help since we provide free binaries for use in this environment. You can download these here; we have both JDK8 and JDK 11 versions available.
If you’re looking to minimise the size of your Docker image as far as possible, I would recommend using JDK 11. That way, you can use the jlink command to build a runtime that is tailored to your specific application or service. I’ve written a blog post about this and demonstrate a simple application where the runtime is reduced from 286Mb to only 39Mb.
If you want to build Java services that exploit the micro in microservices then why not give the combination of Alpine Linux, Musl libc and Zulu JDK a try?