Just like how most programs are available as packages in your favourite distribution's package manager, most programs are available as Docker images on Docker hub, which is as gratis as packages built for distros. And for the ones that don't have an image on Docker hub, you can include the Dockerfile to build it on the spot in the production environment.
The real benefit comes from having the _ability_ to use a different base distribution if required. While alpine is suitable for most applications, sometimes you might be required to run a different distro; perhaps you're packaging a proprietary application compiled for Glibc.
Also, networking isolation is straightforward in Docker. Let's say there's a serious security bug in Postgres that allows you to log in without any password. If someone could perform a RCE in a public-facing website, this would be a catastrophe as they'd be able to exploit the database server as well. With Docker, you can easily put each service in its own network and only give access to the database network to those services that need it. Or you can be even more paranoid and have a separate database and a separate network for each service.
One more feature I'm fan of is the ability to run multiple versions of a software. Maybe some applications require Postgres 9.x and some require Postgres 10.x. No problem, run both in separate containers. You can't do that with regular distributions and package managers (at least in any I know of).
Nix is... tough. I really want to like it, but every time I pick it up I end up having to write some custom package definition for some obscure transitive C dependency with its own snowflake build system. Couple that with poor documentation for existing packages, the terrible search engine experience ("Nix" and "Nix packages" usually turn up things about Unix or "Congress Nixes Aid Package"), and a thousand other papercuts and it just seems to create more problems than it solves. I dearly hope this changes.
Guix is like Nix, but I don't think Nix has an equivalent command to bundle a bunch of packages into a self-contained file for running on arbitrary distros (without Nix/Guix installed).
That's a bit like saying "ORMs are too complex" before proceeding to eventually build your own crappy ORM. I think by accepting docker you gain a lot of support from a developer community which you'd otherwise not see if you assembled your own.
Before proceeding to eventually learn the modern SQL finally and write a couple of stored procedures to stop pumping terabytes of almost-raw data to your "application server" code to be filtered by ORM that is too complex to understand, and in the same time still too stupid to use half of the features your DBMS provides.
You're complaining about a scenario where you might have picked an ORM that didn't met your personal performance requirements. Even if you ignore that you are free to pick any ORM you choose and even if you assume that you have all the time in the world to refactor your project to an experimental setup that was never tested at all, your comment still sounds like a revamp of the old argument on how hand-rolled assembly is always superior to any compiled or interpreted code.
Anyone building out a setup based on cgroups and namespaces will eventually arrive at a poorly specified, bug ridden mini Docker. Might as well get with the program early.
Anyone calling bc from bash script will eventually arrive at a poorly specified, bug ridden mini Mathematica?
Wrt "bug ridden"
> if I were having trouble with something Docker-related I would honestly feel like there was a 50/50 chance between it being my fault or a Docker bug/limitation
Dockerfiles are a part of the configuration
>s3 costs of docker image
Just like how most programs are available as packages in your favourite distribution's package manager, most programs are available as Docker images on Docker hub, which is as gratis as packages built for distros. And for the ones that don't have an image on Docker hub, you can include the Dockerfile to build it on the spot in the production environment.
The real benefit comes from having the _ability_ to use a different base distribution if required. While alpine is suitable for most applications, sometimes you might be required to run a different distro; perhaps you're packaging a proprietary application compiled for Glibc.
Also, networking isolation is straightforward in Docker. Let's say there's a serious security bug in Postgres that allows you to log in without any password. If someone could perform a RCE in a public-facing website, this would be a catastrophe as they'd be able to exploit the database server as well. With Docker, you can easily put each service in its own network and only give access to the database network to those services that need it. Or you can be even more paranoid and have a separate database and a separate network for each service.
One more feature I'm fan of is the ability to run multiple versions of a software. Maybe some applications require Postgres 9.x and some require Postgres 10.x. No problem, run both in separate containers. You can't do that with regular distributions and package managers (at least in any I know of).