We have had two relevant practices for the container images we publish:
- Don't change the user.
- Don't add users.
You can see that with our .NET 7 container images.
.NET Core started out life as a cross-platform project. We naturally wanted to encourage usage on Linux. Across the first couple versions, we figured out how to build a single set of binaries that worked everywhere (e.g. for Linux x64). A key design point of that project was building on an old Linux so that our choice of build OS didn’t unnecessarily limit where .NET apps could be run. That has worked well, using CentOS 7, but it will soon go out of support. There isn't an obvious replacement for CentOS 7, requiring us to adopt a new approach.
We intend to use a combination of Mariner and a streamlined copy of Ubuntu going forward.
The primary aspect of breadth targeting on Linux is linking with the C standard library (libc). Native code (like the .NET runtime) is compiled with a given libc and then is only able to run on distros with a libc version at le
We just shipped a cool new scenario for .NET, which is making it really easy to run .NET 8 container images as a non-root
user.
Friends don't let friends run as
root
We should all get T-Shirts that say that.
Let's take a quick look using our favourite aspnetapp sample. I'm going to use WSL. I'll show you everthing I do. I use the patterns that are easiest for me, which might not be the same for you.
FROM alpine | |
ARG TARGETPLATFORM | |
ARG TARGETOS | |
ARG TARGETARCH | |
ARG TARGETVARIANT | |
ARG BUILDPLATFORM | |
ARG BUILDOS | |
ARG BUILDARCH | |
ARG BUILDVARIANT |
const string Bar = "Bar"; | |
const string DoubleBar = $"{Bar}_{Bar}"; | |
WriteLine(DoubleBar); |
Note: See .NET 5 examples
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net6.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
</PropertyGroup> | |
</Project> |
Battery battery = new("CR2032", 0.235, 100); | |
WriteLine(battery); | |
while (battery.RemainingCapacityPercentage > 0) | |
{ | |
Battery updatedBattery = battery with {RemainingCapacityPercentage = battery.RemainingCapacityPercentage - 1}; | |
battery = updatedBattery; | |
} |
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net6.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
</PropertyGroup> | |
</Project> |
Battery battery = new("CR2032", 0.235, 100); | |
WriteLine(battery); | |
while (battery.RemainingCapacityPercentage > 0) | |
{ | |
battery.RemainingCapacityPercentage--; | |
} | |
WriteLine(battery); |