Easing Deployment Without Containers

In the modern world of Docker and Podman, it seems that deployment is a solved problem. But this is only true if you give up on keeping it simple. There are of course use cases for containers, but sometimes all we need is a small Linux VM to run a few services on, why is it so hard?

Recently I’ve tried with varying degrees of success to run several web services, mostly written in dynamic languages like PHP or Ruby on my server. The experience was horrendous, with lots of weird errors and moving parts that I couldn’t understand. I’m not an expert DevOps administrator but I’ve had my fair share of server administration, at work and at home, so why is it still that hard to set up a new service?

Configuration

A big problem that plagued these projects, was that I needed to configure everything myself from the get-go, instead of relying on some sane defaults. Instead of forcing me to copy some long config file1 and modify some fields, why not use built-in defaults, and let me override what I need in /etc? It’s fine to have a vendor config file in /usr but if you deem packaging your software too hard then at least have some defaults in the program itself.

Dependencies

Dependencies are also a problem, albeit a smaller one. I understand the desire to share the same language runtime between several services, but in practice, it causes a lot more problems than the small gains in saved disk space I get. So instead of forcing me to install rbenv or nvm, consider next time to create a statically compiled program, with everything in it, just like you give to your Windows users. Of course, a proper distribution package is still the preferred way, and in that case, you should rely on the system language runtime, but in any other case, just bundle it.

Additional Files

There are legitimate reasons to publish a directory for your project instead of a single file, but I can guarantee you that those are not the reasons most projects do this. If all I get is an executable, then just give me a single executable file, with all files embedded in it, it’s not a new concept. When you do need additional files, like manual pages or Systemd services, it makes sense to publish a directory but keep the directory structure of the operating system your users deploy to, probably a POSIX one.

I might sound a bit entitled, but now that we have languages like Go and Rust that statically compile out of the box and can easily embed files in them, I don’t think the other languages have any excuse. Deploying a Go service can2 be so easy, why isn’t it the same for other languages? When you write your next program, think about it, maybe even use something like libeconf to read configuration and respect the system file hierarchy.


  1. Which for some reason reside in the source code directory ↩︎

  2. Of course people can still mess it up ↩︎