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.