You should be using Alpine Linux more
For my first real post, I’ll talk about something that’s been done to death: Alpine Linux evangelism. If you thought the Arch Linux people were irritating, oh-ho just you wait, I promise I’ll be worse. Fair warning, this is highly opinionated and delves into at least one Linux holy war (maybe more in the future). If you want to read the drawn-out ravings of a lunatic, this article is for you! If you want to see a more balanced opinion, you should definitely read Drew DeVault’s post: In praise of Alpine Linux
In all seriousness, Alpine Linux is a massively under-appreciated Linux distribution (outside of the container ecosystem). I’m going to avoid rehashing the same arguments I’ve already seen for it. Instead, I’m going to expand on (what is in my opinion) the most important argument for it’s adoption from a philosophical point-of-view.
To summarize, my appreciation for Alpine Linux comes down to one simple factor: Simplicity
If you know anything about me, you know I love simplicity. If given a choice, I’ll choose a simple but highly-functional “thing” over a complex fully-featured “thing” at every possible oppurtunity. Anecdotally, simple tools are typically better at performing a given task, and if a task is too complicated for a single tool, a series of simple tools used together will generally be more effective than a single complex tool. There are obviously some instances where this may not be true, but I believe this logic holds up most of the time, and if it doesn’t seem to apply to a given task, typically you just need a more creative way of solving the problem rather than a more complicated tool.
There are a few reasons why I believe this. To sum them up:
- All things break eventually. Every part of a “thing” can and will break given enough time. Simple fact of the universe, entropy always wins.
- Simple things have fewer parts, and therefore fewer points of failure. Fewer points of failure means things likely won’t break as often.
- In contrast, complex things have many parts, and therefore will break more often. Law of entropy strikes again.
- When simple things break, fewer parts need to be examined to reliably diagnose the issue.
- In contrast, when complex things break, there are so many components that it can sometimes be difficult to tell what broke, let alone fix it.
- It is far more practical for a single person to fully understand every detail of a simple thing, because there are fewer parts that need to fit into their mental model.
- A system with many parts may need a full team of specialists to understand and maintain it properly. Most of the time, that may not be an option.
A good practical example is a 2-stroke bike versus a car. A modern car contains thousands of components that all require varying types and levels of maintenance. Beyond the surface level, most of these parts are so complex that they require specialist knowledge and/or tools to properly maintain or repair.
In contrast, I have a 2-stroke bicycle that I built 5+ years ago. It has 3 major components: the crankcase, the clutch, and the carburetor. The whole system is so simple that it can be summed up in 2 sentences. The carburetor mixes fuel and air, which is fed into the crankcase where the mixture is detonated many times per second. The energy from these detonations is converted to rotational energy for my rear tire, which the clutch can disconnect when I pull a handle. It really is that simple.
I fully understand every component of this bicycle, and now for the most part, you do too even though you’ve never seen it. It’s so simple that if any of it’s components break, I can probably identify and fix the problem in less than 30 minutes with only a ratchet and screwdriver. It was my main mode of transportation for many years, and it only ever developed one major issue while I used it. The barrel on the end of the clutch cable broke free and my clutch got stuck. In the end, it was a 10-minute fix with a spare I already had on-hand.
Anyways, you may be wondering, how does this apply to Alpine Linux?
Alpine Linux is a shining example of pure un-adulterated simplicity. You won’t get a simpler system unless you switch to one of the BSD’s. Only the bare minimum parts needed for basic functionality are included. To put this in perspective, an fully-functional Alpine Linux root filesystem can be as small as ~8MiB. In contrast, the Debian root filesystem on Docker Hub is currently ~121MiB. This is a size increase of ~15x between 2 systems that do almost the same thing.
This simplicity makes it practical for a single person to understand every component in the system. Another giant boon for Alpine Linux is the lack of systemd, which is probably the single most overly-complex piece of software in the Linux ecosystem. Unfortunately, systemd has made it’s way into nearly every major Linux distro available, and has been the harbinger-of-death for simplicity in the Linux ecosystem. It has subsumed everything from system initialization to logging to DNS to basic networking, and in my opinion, now things work worse than they ever have before. Alpine Linux stands out from the crowd here by using OpenRC instead, which is a simple tool that does one thing and does it well.
Unlike systemd units, which require domain-specific knowledge, OpenRC init scripts are an abstraction over an existing widely-understood tool. OpenRC init scripts are simply shell scripts with some syntactic sugar to make them more pleasant to work with, and as such, the fundamentals can be easily picked up by anyone who’s written a shell script before. In contrast, systemd units require you to learn an entirely new thing that is only useful in one place, thus clogging up your mental model.
Larger mental models raise the barrier to entry for understanding a “thing”, and as such, decreases the effectiveness of those who have to work on it. In addition, now you have to learn 2 tools to accomplish the same task on different systems, which compounds the issue. This is not to say a monoculture where OpenRC reigns supreme is a desired outcome, instead I’m saying that new tools should be abstractions of existing proven concepts wherever possible. New tools that could improve upon proven concepts but choose not to are disrespectful of your time as an engineer.
One could argue that knowledge of systemd units is to some extent transferrable to OpenRC, and this is not entirely false, but it’s not really true either. To take this to the logical extreme, you could say the skills are transferrable simply by virtue of being written in the English language, but this is obviously disingenuous. The details are the most important part. For example, systemd-resolved and resolv.conf
both handle DNS resolution, but they are very different tools in practice.
resolv.conf
contains DNS information in a simple space-seperated format, and libc uses this file within the application when it resolves names. Systemd-resolved is a whole recursive DNS server that runs on your system which you are expected to point the existing resolv.conf
to. Systemd-resolved does provide benefits on paper, like caching, but I’d argue that the means needed to achieve this are an unnecessary complication.
Most businesses already run their own internal caching resolvers, and most home users have a caching resolver built-in to their router. I’ll go a step further and say that caching DNS responses externally is more effective anyways because you can share the cache between multiple systems at a time. This approach not only works better, it also fits cleanly into the existing model for resolv.conf/libc. That’s the whole reason it’s always been done that way.
This is not to say that the traditional ways are better because they are traditional. If a new means of doing something appears that has obvious tangible benefits that make the switching cost worth our time, we can and should do things that way. In this instance, the traditional way of resolving and caching DNS names works well enough that we’ve never really made any major changes to the concept. In contrast, systemd-resolved is different for the sake of being different and offers no tangible improvements to show for it.
To conclude, Alpine Linux is simple and highly traditional, but in this instance, it’s a good thing. I personally hold deep criticisms of tradition and conservatism from a philosophical point-of-view, but as with all things, there is nuance. In this case, the return to traditionalism offered by Alpine Linux is a huge boon that is made apparent every time I use it or work on it’s components. You really just have to give it a shot (and stick with it for a while) to truly understand just how pleasant it is to work with. I whole-heartedly recommend it as the base for almost any system you build, even if it’s not a container.