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.
rich@mazama:~$ curl -Lo dotnet.tar.gz https://download.visualstudio.microsoft.com/download/pr/e2578737-231b-493c-a6ee-f181496fe679/18038808d2621094ebe172ca011a7c22/dotnet-sdk-8.0.100-preview.1.23115.2-linux-x64.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 180M 100 180M 0 0 67.1M 0 0:00:02 0:00:02 --:--:-- 67.1M
rich@mazama:~$ mkdir dotnet
rich@mazama:~$ tar -C dotnet/ -xf dotnet.tar.gz
rich@mazama:~$ ./dotnet/dotnet --version
8.0.100-preview.1.23115.2
rich@mazama:~$ git clone https://github.com/dotnet/dotnet-docker
Cloning into 'dotnet-docker'...
remote: Enumerating objects: 87697, done.
remote: Counting objects: 100% (4692/4692), done.
remote: Compressing objects: 100% (1083/1083), done.
remote: Total 87697 (delta 1891), reused 4494 (delta 1752), pack-reused 83005
Receiving objects: 100% (87697/87697), 15.05 MiB | 24.62 MiB/s, done.
Resolving deltas: 100% (39728/39728), done.
rich@mazama:~$ cd dotnet-docker/samples/aspnetapp/
rich@mazama:~/dotnet-docker/samples/aspnetapp$ vi Dockerfile
rich@mazama:~/dotnet-docker/samples/aspnetapp$ cat Dockerfile | grep 8.0
FROM mcr.microsoft.com/dotnet/sdk:8.0-preview AS build
FROM mcr.microsoft.com/dotnet/aspnet:8.0-preview
rich@mazama:~/dotnet-docker/samples/aspnetapp$ vi aspnetapp/aspnetapp.csproj
rich@mazama:~/dotnet-docker/samples/aspnetapp$ cat aspnetapp/aspnetapp.csproj | grep 8.0
<TargetFramework>net8.0</TargetFramework>
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker build --pull -t aspnetapp .
[+] Building 55.1s (15/15) FINISHED
Ports:
- .NET 8 defaults to port 8080: https://github.com/dotnet/dotnet-docker/blob/0f7ed9ce44b4aff3456b152b8cb4441c0617c120/src/runtime-deps/8.0/jammy/amd64/Dockerfile#L31
- .NET 6 (and 7) defaults to port 80: https://github.com/dotnet/dotnet-docker/blob/0f7ed9ce44b4aff3456b152b8cb4441c0617c120/src/runtime-deps/6.0/jammy/amd64/Dockerfile#L19
- The port mapping needs to address that (host:container mapping).
Note: Here, I'm running with -d
since it easier for what I'm trying to demonstrate. Normally, you wouldn't do that, but use -it
instead.
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker run --rm -d -p 8080:8080 aspnetapp
bd3db4a7fafda88e68d17b596c53cdb57e1c05df61aa47f6b674d5b71976277a
rich@mazama:~/dotnet-docker/samples/aspnetapp$ curl http://localhost:8080/Environment
{"runtimeVersion":".NET 8.0.0-preview.1.23110.8","osVersion":"Linux 5.15.79.1-microsoft-standard-WSL2 #1 SMP Wed Nov 23 01:01:46 UTC 2022","osArchitecture":"X64","user":"root","processorCount":16,"totalAvailableMemoryBytes":67430023168,"memoryLimit":9223372036854771712,"memoryUsage":34017280}
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker kill bd3db4a7fafda88e68d17b596c53cdb57e1c05df61aa47f6b674d5b71976277a
bd3db4a7fafda88e68d17b596c53cdb57e1c05df61aa47f6b674d5b71976277a
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker run --rm -d -p 8080:8080 -u app aspnetapp
6b1a301e36109b0c78546f02d7f865de04f02bd6e221ff8578f5b6496d3e1fa4
rich@mazama:~/dotnet-docker/samples/aspnetapp$ curl http://localhost:8080/Environment
{"runtimeVersion":".NET 8.0.0-preview.1.23110.8","osVersion":"Linux 5.15.79.1-microsoft-standard-WSL2 #1 SMP Wed Nov 23 01:01:46 UTC 2022","osArchitecture":"X64","user":"app","processorCount":16,"totalAvailableMemoryBytes":67430023168,"memoryLimit":9223372036854771712,"memoryUsage":31543296}
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker kill 6b1a301e36109b0c78546f02d7f865de04f02bd6e221ff8578f5b6496d3e1fa4
6b1a301e36109b0c78546f02d7f865de04f02bd6e221ff8578f5b6496d3e1fa4
This pattern only works reliably with root
. In some scenarios, non-root
users are allowed to listen on port 80, too. It depends on the rules of the given environment.
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker run --rm -d -e ASPNETCORE_HTTP_PORTS=80 -p 8080:80 aspnetapp
9249068c141363d83c22ee14e37f75567980109a199af67376eee532bba43632
rich@mazama:~/dotnet-docker/samples/aspnetapp$ curl http://localhost:8080/Environment
{"runtimeVersion":".NET 8.0.0-preview.1.23110.8","osVersion":"Linux 5.15.79.1-microsoft-standard-WSL2 #1 SMP Wed Nov 23 01:01:46 UTC 2022","osArchitecture":"X64","user":"root","processorCount":16,"totalAvailableMemoryBytes":67430023168,"memoryLimit":9223372036854771712,"memoryUsage":31428608}
rich@mazama:~/dotnet-docker/samples/aspnetapp$ docker kill 9249068c141363d83c22ee14e37f75567980109a199af67376eee532bba43632
9249068c141363d83c22ee14e37f75567980109a199af67376eee532bba43632