How .NET container images are maintained
devblogs.microsoft.com
devblogs.microsoft.com
“Analise” has a very different meaning, one that you probably don’t want to Google on a corporate computer.
I have to imagine at some point probably very soon all of the time spent maintaining and hacking in the NT kernel to work in a container world is just throwing good money at a vanishingly small segment of the market.
kudos to this team for being on the ball and supporting ARM and ARM64 images though. Now when can we actually run ARM64 stuff on Azure....
What I do at my day job would be considered legacy tech here on HN but my company is a multi million dollar profitable business working in the B2B sector. Our customers don't want flashy websites, they want software that works over many years with minimal maintenance burden running on their own hardware.
Microsoft Windows is still dominant in the business world because the often external IT knows how to work on it and most of the time it just works.
These and many other companies also have generations of (not quite as old) Windows applications that aren't going anywhere anytime soon either.
These companies want to manage it all in a modern way. Sometimes, it's part of the migration strategy.
Valid question, but not exactly what the article is about. .NET Containers != Windows Containers
From the article:
> . We publish updated .NET images for Alpine, Debian, and Ubuntu
Also outside HN universe, Windows servers are a thing, so it is not only .NET, there are also Java and C++ applications.
I work at a consultancy for enterprise-size orgs, and Windows servers are indeed still frequently used - but almost exclusively on-prem, and I've never even once come across Windows containers being used. Seems the shift to the cloud, and Microsoft's shift to OSS and Linux love, has tamed even the most fervent of Microsoft shops. 10 years ago you'd be laughed at if you suggested anything other than Windows, but now it's the default for anything in the cloud.
All the cloud based deployments I have done, other than a couple of serverless microservices on AWS Lambda, have been done on Windows and that won't change for the foreseeable future in what concerns the kind of customers I work with.
In fact, it is a bit ironic that instead of getting advises from cloud experts, I am the one with my lower skill set in the domain, to have to explain to them what is to be expected for production delivery.
Similarly with WCF. It's something I used to use a decade ago (though I admit I was never a fan), but haven't seen it used in eons.
Don't take marketing for the full use in production environments.
Also we can keep doing this game, there are plenty of enterprise tools I can list.
.NET Core is the Python 3 of .NET world.
You are correct that you don't get a VS designer, but I've personally always favoured a code-first approach anyway, so this never affected me.
> .NET Core is the Python 3 of .NET world.
I see where you are coming from, but I don't think I agree. There is still a large segment of Python 2 devs, and for many, there isn't a particularly compelling reason to move to Python 3. Dotnet Core is different, in that there are very compelling reasons to move: cross-platform (massively important in our new cloudy world), performance, and of course ongoing support. There are for sure a small hardcore of sad dotnet devs stuck on Framework because of some legacy libraries, but I reckon the majority made the move to Core a long time ago.
The .NET Framework version is working fine and has been for years. That's why my company won't switch in the near future. Marketing and reality are just too far apart.
That's tooling, not Dotnet Core itself. As an aside, I think there is even a WinForms GUI editor in Jetbrains Rider now.
> Marketing and reality are just too far apart
I mean, that's your opinion, but there are millions of Dotnet Core devs for whom the reality is as wonderful as promised. If you still have to work with legacy libraries or maybe WinForms, then of course I understand where you are coming from, but I don't think it's fair to tar the whole of Dotnet Core based on some limited failings that affect only a minority.
Just look at the github issues of everyone on the UWP/WinRT disgruntled with the lack of roadmap for .NET Native, or how WPF has taken one year to ramp up a new team, after they sent everyone away. Worse it seems that WPF bug fixes are being done from other side of the globe in some offshoring deal.
Real life on the trenches is not like on Channel 9 TV.
I absolutely do not dispute that anyone involved in building Windows-only desktop apps is not going to be satisfied - but they are absolutely in the minority.
As a consultant, I don't just see the workings of a single org - I work across several orgs every year. When Core first became a thing, some were slow to take it on, which was understandable considering the confusing messaging from Microsoft. But it's been around for a long time now, and Microsoft's messaging and intentions became clear. What I now seen is huge uptake of Dotnet Core - way, way more is now on Core than Framework, and I haven't seen anything new being built on Framework for at least a couple of years.
On my side, I am yet to see a new project done on Core besides some tiny micro-services on department level.
As mentioned on another thread answers, still waiting on SharePoint and Dynamics running on Core.
So yeah, we'll need to disagree.
The current LTS release of .NET Core 3.1 has a broken socket implementation that can lead to deadlocks on Linux and macOS.
Microsoft will not fix it in 3.1 LTS and recommends using .NET 5, which is not an LTS. If you are a company that is deploying multiple times a day, that's probably fine. If you are a company that keeps the lights on with about 5 devs for a few hundred customers with on-prem setups, this is just unacceptable and doesn't even have anything to do with legacy libs.
Admittedly it's just from what Raymond Chen's blogged about, but it seems to me that Microsoft had a different "corporate attitude" back then, so to speak.
I don't think Java applications have dependencies to Windows that often, and it's a pretty bad idea to use C++ in server applications.
Sure Java runs on Linux, that doesn't mean many shops want to build the human skill set to manage those boxes.
As for C++ and server applications, in what languages do you think database servers and similar high performance servers are written on, most of the time?
Even Microsoft is using Linux containers for production dotnet deployments.
Don't judge what Microsoft is doing, with the .NET Core teams are marketing for.
All the other tooling we use is open source. You can find our build infrastructure at https://github.com/dotnet/docker-tools. There's a tool there called image-builder that provides much of the functionality. I've written a blog post on how we use Azure Pipelines to manage the builds: https://devblogs.microsoft.com/dotnet/how-the-net-team-uses-.... Between image-builder and the pipelines, there's some automation that automatically rebuilds our images whenever a parent image changes.
This is a strong assertion with no further explanation. It reads like a generic truth about container images, but it's certainly possible to achieve this, as referenced later:
> Sidebar: Various folks in the container ecosystem are looking at enabling deterministic images. We welcome that. See Building deterministic Docker images with Bazel and DETERMINISTIC DOCKER IMAGES WITH GO MICROSERVICES.
I'll agree that docker makes it _really_ difficult to build and consume reproducible images (for a variety of reasons, see https://github.com/google/go-containerregistry/issues/895#is... and https://twitter.com/lorenc_dan/status/1343921451792003073 for a sampling of interesting ones), but there is more to the container ecosystem than docker or Dockerfiles.
Shameless plug: I help maintain ko (https://github.com/google/ko), which can achieve reproducible builds for go projects without much fuss. It also leans heavily on go's excellent support for cross-compilation to produce multi-platform images, trivially.
> There are two cases where the container-diff tool will report that the registry and local images that you are comparing are the same (in terms of Docker history lines), but will be misleading because the images are actually different.
While container-diff is great, it can obscure what's really going on a bit. If you're interested in uncovering exactly why the digest of the image you built is different from what was published, please forgive another shameless plug for crane (https://github.com/google/go-containerregistry/blob/main/cmd...), a tool I wrote to expose most of the functionality of go-containerregistry (https://github.com/google/go-containerregistry), which is the library both container-diff and ko use under the hood.
Forgive the sparse documentation, but it should be relatively straightforward for anyone familiar with the registry API and data structures, as the commands map pretty directly to registry functionality. Using crane, you can easily inspect the image in the registry directly to compare the manifests and blobs that make up an image.
For example, one reason that the digests might never match is that these images are somewhat strangely wrapped as singleton manifest lists: https://gist.github.com/jonjohnsonjr/ffba104ca504b5bb4a1f227...
It makes some sense to me that they might want to do this to prevent folks from pulling this on windows, but usually you would only encounter manifest lists for multi-platform images. Even if these builds were reproducible, you would have to compare the digest of what you built with sha256:9a210bb9cbbdba5ae2199b659551959cd01e0299419f4118d111f8443971491a -- not the sha256:fb1a43b50c7047e5f28e309268a8f5425abc9cb852124f6828dcb0e4f859a4a1 that docker outputs, as shown in the article.
The tag used for this example (mcr.microsoft.com/dotnet/sdk:5.0-alpine) has since been updated. Comparing this with the original using container-diff just tells us that the size changed: https://gist.github.com/jonjohnsonjr/90c2def551833c8cacf3264...
But looking at the actual manifests, config blobs, and layers using crane is often faster and more interesting: https://gist.github.com/jonjohnsonjr/283eab27d996b2f4cc04553...
My intention with crane is to be easily composable so that you can use familiar tools like tar, sort, diff, jq, etc.
(To be fair to container-diff, you can use the -t flag to show similar things.)
I realize this is not really the point of the article, but it's a huge pet peeve of mine that everyone has just given up on understanding what's going on with their images because the tooling UX makes everything so opaque. If the digest of something doesn't match, you should know why! It's as if `git push --force` was on by default and everyone has just accepted that reality.
Now to read the rest of the article :)
I wrote the article (although you probably figured that out).
Oh, and thanks for caring so much about reproducibility. We talk about this topic a fair bit in the .NET toolchain, and have enabled it over many years of investment. A lot of it comes down to timestamps or pathing (as you know).
Slightly off topic but since you linked to his Twitter account, everyone should check out Dan Lorencs articles. There is some interesting articles about Golang, kubernetes and other Ops-like things.
I only wish I could get his stuff into my RRS feed so that I didn't miss it.
I don't know what you are 'allowed' to write about but I'd love to know how GKE keeps on overriding it's settings and what can be changed and what cannot. We've had problems with the metrics server in the past crashing and most of the setting we edited by hand were overwritten. Fortunately, we found one way to change something, it stayed and our metrics server recovered.
Also, insights into what happens when GKE does a node pool upgrade would be useful. We had an outage because of an upgrade a couple weeks ago that I have to take a deep dive into. I am guessing we are missing node anti-affinity.
Thanks!