This issue happens with Linux Azure Container Instances (ACI) after upgrading the app to .NET 8; the exact same code works targeting .NET 6 (i.e. if I only change <TargetFramework>
in the .csproj
and the publish profile).
I get the following exception when launching an ASP.NET Core 8 app in an ACI:
fail: Microsoft.Extensions.Hosting.Internal.Host[11]
Hosting failed to start
System.Net.Sockets.SocketException (13): Permission denied
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions.CreateDefaultBoundListenSocket(EndPoint endpoint)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint endPoint, ConnectionDelegate connectionDelegate, EndpointConfig endpointConfig, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__DisplayClass28_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.EndpointsStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(ListenOptions[] listenOptions, AddressBindContext context, Func`2 useHttps, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
Unhandled exception. System.Net.Sockets.SocketException (13): Permission denied
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions.CreateDefaultBoundListenSocket(EndPoint endpoint)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint endPoint, ConnectionDelegate connectionDelegate, EndpointConfig endpointConfig, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__DisplayClass28_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.EndpointsStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(ListenOptions[] listenOptions, AddressBindContext context, Func`2 useHttps, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Program.<Main>$(String[] args) in E:\MyProject.Web\Program.cs:line 42
This happens if I try to make Kestrel listen on ports 80, 443, or both. I don't get any more information with Trace
-level logging.
This is what I tried:
appsettings.json
under Kestrel__Endpoints
, the ASPNETCORE_HTTP_PORTS
and ASPNETCORE_HTTPS_PORTS
environment variables, or with UseKestrel()
.--privileged
with az container create
(as well as --allow-escalation
) but nothing changed.I can't reproduce this locally under Windows.
The container image is published self-contained.
Can somebody help me understand what I may be doing wrong? Is this perhaps an undocumented breaking change, in .NET 8 or how ACI supports .NET 8?
Cross-post from an aspnetcore
discussion since nobody replied there for a week.
Update: I cross-posted to Microsoft Q&A for visibility.
Update 2: I dug some more and found that actually this might be the breaking change relevant to this issue, not the default port change: New non-root 'app' user in Linux images. Also see the blogpost it links. And sure enough, with .NET 6 the container's user is root
, and with .NET 8 it's app
.
I tried
az container create `
--run-as-group 0 `
--run-as-user 0 `
...
to run the container as root but it still runs as app
. Adding USER root
in the Dockerfile doesn't do anything either because the Dockerfile has no effect for Azure Container Instance, they use az container create
as a substitute. I also tried setting ContainerUser
with <ContainerUser>root</ContainerUser>
but no luck.
Found the solution. It was actually setting ContainerUser with <ContainerUser>root</ContainerUser>
in the csproj. No other changes necessary.
So, all in all, compared to the .NET 6 version, my app has the following changes to target .NET 8:
<TargetFramework>net8.0</TargetFramework>
in the csproj.<TargetFramework>net8.0</TargetFramework>
in the pubxml used by az container create
.<ContainerUser>root</ContainerUser>
in the csproj, see below the context.Full section of the csproj:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<UserSecretsId>MyId</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
<ContainerUser>root</ContainerUser>
</PropertyGroup>
I did try this before, but apparently, I messed up something during publishing, but now it's clear.
I also opened an issue to clarify this in the docs: https://github.com/dotnet/docs/issues/39082.