Ask HN: Do you run apps bare metal?
So, I am working on a side project and the way I deploy my (golang) application is basically:
- build binary
- copy binary, config files and static assets to the production server
- do blue green deployment (with nginx) to get zero-downtime deployment
- profit
(This is automated of course! I use Ansible, and I can easily rollback if needed. I can also deploy the same app to multiple machines if needed).
On my local machine I use Docker to test the Go code, but I don't really see the benefit of deploying my Go app in a container. My colleage told me "it's easier to deploy Docker containers. You just pull the image and voila!". I don't see how my approach could be "more complicated". Also, isn't my approach better in terms of performance? If my golang app runs "bare metal" instead of via a container, then sure the performance should be better, right?
In this technical retrospective (2021), @sdevonoes shares practical architectural lessons learned from running, scaling, or migrating production software under lean constraints.
HN engineers debated the tradeoffs between cloud convenience and raw server economics, database indexing strategies, and resisting premature architectural complexity.
It would help to clarify some words:
"Bare metal" means that your application is running on the same OS that is also running the raw hardware (metal), aka no virtualization. Containers are not (generally) the same as virtualization.
The analog to bare metal is virtualized, where the hardware your program is seeing is not necessarily the hardware that is running on the actual host machine.
A docker container could ostensibly be considered running on bare metal. A container is really just isolation but the parent OS/kernel is in command. Here is a graphic that illustrates the differences: https://www.sdxcentral.com/wp-content/uploads/2019/05/ContainersvsVMs_Image.jpg
What you are really asking is do you need an abstraction layer or orchestration tool to manage doing this.
The short answer is that no you do not need it at all. If you can DIY this and are happy with it, that is sufficient. For example, a current deployment process for one of my clients (EC2 environment) involves stopping a custom systemd service, pulling the new binary/deps and then starting the systemd service. Really simple with a small instant of downtime, but within this environment that is not a problem.
Your performance should not noticeably differ (on linux) between docker and just running as an uncontainerized process on the host. There's almost no difference as far as the kernel is concerned; it just tags your process slightly differently (different kernel namespaces and cgroups, but these apply to every process).
Bare metal usually refers to running without hardware or software virtualization (kernels within kernels), and if that were the case (docker on linux does not virtualize) it would be meaningfully faster, but that's not the case here.
The primary benefits you get from Docker may not be immediately apparent, so go for whatever works. Eventually, you'll probably find that it's substantially easier to scale out appropriately and automatically with some sort of orchestration tech, which is nearly all built on containers these days. Don't sweat it til you need it but at the same time, it's easier to learn sooner than when you're knee deep in tech debt for a dozen services.
Yes.
Our contract is that a unit of deployment is a .tar.gz file, and inside that there is an executable file bin/run which starts the app. We build apps in a few languages, but they all have a start script like that.
You can use static or dynamic linking, compiled or interpreted languages, anything you like, as long as the start script sets it up correctly. For Go apps the script can be trivial.
Tarballs must be self-contained - binaries, libraries, config files, static assets. We make an exception for interpreters, because those are huge and change slowly. Those are manually installed in /opt/something. I'd like it if we did something more disciplined and reproducible, but it's good enough for now.
We don't have many machines. Maybe 20? You can get a lot done with 20 full-size physical machines.
I don't see how something like Docker would help us here. It would just be the same, but less hackable.
There's nothing really wrong with what you're doing. Apps were deployed like that for decades before docker came along.
To my mind the main benefit of containerization would be that the
would be bundled together inside the container, so there is less risk of you running a half-baked version where (e.g.) the binary gets updated but the other files don't. However since you're using Ansible to deploy, that risk already feels small. You could also consider using the embed feature in go1.16 to bundle all the assets inside the binary.
Arguably there might also some security benefit to running in a container, but I wouldn't want to try and make that argument without knowing a lot more about the specific details of your binary's behaviour.
Yes, I frequently don't use any operating system and write bare metal C code, usually for Zynq (normally RFSoC or MPSoC class) FPGAs, although I also frequently use a Microblaze soft processor with it's entire memory in BRAM when doing initial system bring up (say for a new board).
Lots of people in here don't know what "Bare metal" means. There's no operating system - at all. Anything else is not bare metal.
To go further: Sometimes (if you're bringing up a new processor design) you don't even get cstdlib - you have to write it (or the processor's architecture won't even support C!). "Bare metal" means exactly that - it isn't the same as "no virtualization"... at all.