Build the damn app one time using SQLite on a single box. Then, figure out if the market even gives a shit about it. Building out a multi-cloud application architecture for your first prototype is a massive mistake. You don't need containerization tech if you can clone your application, hit F5 in visual studio, and the whole stack starts up automagically. You will probably find the performance of a single, powerful machine to be more than enough for your expected user base. SQLite can handle a fuckload of 'concurrent' writers if you know what you are doing.
There are now framework features available in some areas that help to obviate the need for containerization. If you are a .NET shop, look into self-contained deployments:
https://docs.microsoft.com/en-us/dotnet/core/deploying/#publ...
We have been using this deployment approach for ~3 years now and we have yet to have a single situation where a required dependency was missing or broken in production. And, we deploy to a very wide range of customer environments with all sorts of horrible IT practices applied to them.
Imagine being able to unzip a build of your software to a blank windows/linux server and expect that it work flawlessly 100% of the time, regardless of any prior/lack of configuration or other supporting dependencies on that machine.
YES YES YES
I am certain at this point they're doing it only to show off and to have something complicated enough to talk about the train new hires on.
One big argument for Docker is no dependencies, but Go and C# already can create fat native binaries that have no dependency on anything else (no .net framework or even VM, all native, same thing in Go). I believe Rust too offers the same thing. There is no excuse with all those different languages all supporting that.
There absolutely are complicated apps that justify Docker and k8s, but the vast majority in the real world do not fall into that, and most certainly that includes small ad-hoc internal services.
Using Nix, you can build a self-contained deployment for just about any language/rutime you can imagine, and the target machine doesn't need to run Nix.
Containerization isn't really that hard. At its most basic level, a Dockerfile is just a list of commands needed to build/run your program. I'd personally much rather have that as a sort of self-documenting build process than dig into "how does Visual Studio build things? Why is my local dev build process (F5 in Visual Studio) so different from our release build process (msbuild commands or whatever)?" Or worse, "why does our release process involve Joe hitting F5 on his machine?"
Deploying a container isn't that hard - I agree that k8s and such is likely overkill for most startups. A basic "docker run" bash script or something in that vein is not terribly difficult to write, maintain, and hook up to CI/CD. Even so, with growing cloud support from GCP/AWS/Azure etc, the leap from "We built an isolated container for local dev" to "Now we run that container in prod via k8s" is shrinking.
As you pointed out, there are other ways to do this, but at least right now Docker is fairly widely used and it's not limited to certain toolchains/languages. Using something just because it's popular seems like a bad idea on the surface, but if two tools are both reasonably sufficient, I'm definitely leaning towards the more widely used one - it means it's more likely new hire will be familiar with it on some level, there's more blog posts with best practices, etc.
> Imagine being able to unzip a build of your software to a blank windows/linux server and expect that it work flawlessly 100% of the time, regardless of any prior/lack of configuration or other supporting dependencies on that machine
I mean, that's basically _why_ Docker exists.
> I mean, that's basically _why_ Docker exists.
It is, but Docker isn't it. At the least, Docker won't run side-by-side with Virtual Box on Windows, so "regardless of prior configuration" is not met. In general, Docker adds an extra dependency on top of a blank system: Now you need to get Docker set up and running first, and then you can deploy your app. The alternative in question is about controlling the build to such an extent that you can reliably deploy the artefacts onto any system without having some runtime environment prepared.
For example, at my last job, before we switched to Docker, a client dev that wanted to run a local backend had to install postures, apply initial schema, and then download and run the app. Not only was this a bunch of steps the client devs weren't familiar with, it led to backend devs being reticent about using the most appropriate tool for new features (e.g. shoving service discovery awkwardly into SQL instead of into something like etcd - and before anyone says "well that's fine" or "just do xyz instead," realize that's just an example of several). It was annoying to client devs to have to add new tools all the time, and annoying to backend devs to have to constantly troubleshoot misinstallation / misconfiguration.
When we switched to Docker, the client devs could run the backend without having to manage anything. Install docker (once), then run a very basic script that basically just ran "docker-compose pull; docker-compose up".
I don't generally want to be able to deploy to arbitrary environments. I want something that is easy to build, builds consistently, and lets all my fellow devs run whatever host they need to be maximally effective.
On Windows, it's true, if you need Virtual Box specifically then you can't use "Docker for Windows". You could either move the VB stuff into Hyper-V, or run Docker directly on a VB VM (a little less turnkey, but not particularly difficult).
It's obviously not the intended use case, but it can have the advantage of plugging in much nicer with your existing tooling.
As an example, if I have a Kubernetes cluster, and a new app that needs a full VM.
My options are to containerize it (it likely already comes this way), and let Kubernetes scheduled it on it's own VM, or use a different tool in order to manage the unique VM for this app.
Unless there are reasons to avoid the containerize approach, I'm going to stick with the existing tooling rather than add additional complexity.
Most cases I've seen the apps don't need more than a two dozen megabytes out of the gigabytes in the VM. It was crazy seeing how much resources were being wasted for no good reason.
So docker is basically just a package manager and supervisord replacement for us because both ops and devs find it easier to build do deploys with containers than software on the host.
We use no actual features of docker, basically everything is disabled. We could use podman but that would be more effort for the same thing.
If people paying the money knew the amount of waste being done...
Rootless mode helps provide some isolation and individual machines also provide some isolation.
Anyone who can launch a container with the `--privileged` flag has the ability to read the host VM's disks, or on a physical machine even update the bios etc... Launch a container with that flag and play with mknod and dd for the hosts root drive if you don't understand that attack vector.
The question you should ask is why you aren't using user namespaces or isolated machines if you are attempting to follow the least privileges and zero trust models.
Whatever restrictions you want to apply to the Docker, can be applied to the binary as well when invoking it.
1) Containers reduce the number of shared dependencies between the VM and the application. A container based on alpine will even be using musl libc vs glibc. And a VM running on a private cloud or different cloud providers will require different dependencies. As dependency hell is NP-complete, increasing the number of dependencies dramatically increases the effort of testing, trouble shooting, and maintaining a system. The simplified contract between a container and it's host vs a binary on a VM reduces that cost.
2) Instantiation time is much longer for a VM than a container.
3) Container management systems like k8 etc... tend to have more robust health checking, service registration, and recovery tools. If one is using containers already the cost of maintaining a parallel infrastructure for VMs is often high.
4) Developers can often run a container on their desktops/laptops and iterate faster as they avoid the challenges and costs in maintaining dependencies called out in #1 or the expense and time of spinning up development instances.
There are companies and groups that use containers and container management systems because they are the hot new thing, but even before the public cloud or even high density VMs were a reality I was on a team that leverage Linux VServers for all core services. It is still the only company I have ever been at where we could actually switch over to a cold DR site with everything from DNS to Oracle EBS being up in less than half an hour. All with only using rsync and tar for a publicly traded company.
You can get around package version selection being NP-complete by putting on other constraints like enforcing semantic versioning and auto updates. But IMHO using namespaces(containers) is one solution one should consider.
Here is a link to a paper that will describe the package dependency problem generalizes to the NP-complete SAT problem.
For me, containers are a way to limit that problem to being one of the container host only needing satisfy a contract for a far more limited set of needs (kernel ABI, network, storage).
https://hal.inria.fr/hal-00697463
Your needs and challenges may be different, but containers tend to be a good option for many of the needs I have run across.