Yes I'm aware MS makes it easy to build containers and even single executables, but languages that compile down to an ELF are pretty much a requirement once your deployments are over the 10k containers mark.
Yes I'm aware MS makes it easy to build containers and even single executables, but languages that compile down to an ELF are pretty much a requirement once your deployments are over the 10k containers mark.
Why? I routinely put compiled .NET programs into containers.
It's also easy (easier than Rust even) to build on Mac targeting a Linux image.
> Create a hello world dotnet container
The container image is 10.9 MiB. The binary is 1.2 MiB.Stackexchange famously is a dotnet application that runs on a handful of fairly (but not unreasonably) large computers. 10k containers is either "you are Facebook", or you're wasting a lot of that in some other way.
It's also well-suited for that. Of course, you won't end up with a tiny Go docker image, but this doesn't matter.
You need 10K containers for Node and Python apps because they use a single threaded runtime! The best way to scale these is to deploy many small containers.
The .NET runtime is fully multithreaded and asynchronous and supports overlapped I/O. It scales to dozens of cores, maybe hundreds in a single process. The built in Kestrel server is full featured including HTTP/3 and TLS 1.3! You don’t even need NGINX in front of it.
Not to mention that unlike most Linux-centric programming languages, it deploys reliably and consistently without needing the crutch of containers. You can simply copy the files to a folder on the web server(s), and you’re done. I’ve actually never seen anyone bother with containers for an ASP.NET web app. There is very little actual benefit, unlike with other languages where it’s essentially the only way to avoid madness.
PS: Every Node app I’ve ever deployed has been many times slower to build and deploy than any ASP.NET app I’ve ever seen by an order of magnitude, containerised or not. Go is comparable to C# but is notably slower at runtime and a terrible language designed for beginners too inexperienced to grok how exceptions work.
I understand that you're getting a roughly 100mb dist directory for a .Net web app, and that it uses quite a bit of ram.. but people also use Node and Java which have similar issues.
Don't get me wrong on this, I'd like to use Rust+Axum a lot more and C# a bit less.. but I don't dislike C#.
That being said, I'd much prefer to deploy a C# application over Node or Java, no argument there. But saying "I wish more startups were using C#" makes me wince. C# seems well-suited for the monolith-architected VM-image-deployed strategy of the early 2000s, but it's pretty close to being the exact opposite of modern best practices. And unfortunately it's kinda unfixable in a language that depends on a VM execution environment.
I'm sure all this is short-lived however -- I'm relatively confident we'll see deployment best practices converge down to "use whatever language you want but you must compile to WASM" in the next decade, so the warts of devs' chosen language aren't an ops problem anymore.
That said, you get a lot of functionality in the box and nearby out of that extra resource usage and it doesn't really grow by much under load.
Beyond that, there's nothing particularly wrong about having a mostly monolithic backend for a lot of things, I would say most applications are better served starting with a more monolithic backend in a mono-repo with the FE.
https://learn.microsoft.com/en-us/dotnet/core/deploying/nati...
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/n...
This is a solved problem within csproj to do dotnet publish to OCI containers already. I even have some csproj override to magically add it to every console projects in the solution.
The biggest problem IMO is because of the JIT generated code not being able to be saved, so it will always be regenerated on the fly, and compound that with a not so state-of-the-art GC (wish we have ZGC someday), it will create brief moment of latency very easily and making the timing fat-tailed.
NativeAOT and ReadyToRun remedies this problem by compiling ahead of time, but you trade space with time.
Why?
Go and Rust produce native binaries, I wish C# had an official native compiler without the big runtime needs of .Net.
Publishing your app as Native AOT produces an app that's self-contained and that has been ahead-of-time (AOT) compiled to native code. Native AOT apps have faster startup time and smaller memory footprints. These apps can run on machines that don't have the .NET runtime installed.
Their target is probably not entirely greenfield projects (although I wouldn't mind it myself), but rather those with existing investments that start new projects that still want to share some parts.
https://learn.microsoft.com/en-us/dotnet/standard/serializat...
There's been some work on CoreRT and a general thrust to remove all dependencies on any reflection (so that all metadata can be stripped) and to get tree-shaking working (e.g. in Blazor WASM).
It seems like in general they're going in this direction.
What problems does this cause?