Unable to start Kestrel. System.IO.IOException: Failed to bind to address http://0.0.0.0:80: address already in use / connection refused on mapped port
ID: dotnet/docker-aspnet-port
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 8 | active | — | — | — |
Root Cause
ASP.NET Docker port binding issues occur when Kestrel listens on a different port or interface than what Docker exposes. In .NET 8+, the default port changed from 80 to 8080 and the app listens on localhost instead of 0.0.0.0 by default. Fix by setting ASPNETCORE_URLS or ASPNETCORE_HTTP_PORTS environment variable and using EXPOSE with the correct port.
genericWorkarounds
-
92% success Set ASPNETCORE_HTTP_PORTS environment variable in the Dockerfile
Add to Dockerfile: ENV ASPNETCORE_HTTP_PORTS=8080 and EXPOSE 8080. Then run with: docker run -p 5000:8080 myapp. For .NET 8+, ASPNETCORE_HTTP_PORTS is the preferred way to set the port. Alternatively use: ENV ASPNETCORE_URLS=http://+:8080 which also binds to all interfaces
-
90% success Use the official ASP.NET Docker base images and match port configuration
Use mcr.microsoft.com/dotnet/aspnet:8.0 as the base image. This image sets ASPNETCORE_HTTP_PORTS=8080 by default. Ensure your docker run command maps to port 8080: docker run -p 80:8080 myapp. If you need a different port, override with ENV ASPNETCORE_HTTP_PORTS=<port> and update EXPOSE and -p accordingly
Dead Ends
Common approaches that don't work:
-
Using EXPOSE 80 in Dockerfile without configuring Kestrel to listen on port 80
80% fail
EXPOSE is only documentation metadata; it does not actually configure port binding. In .NET 8+, Kestrel defaults to port 8080, so EXPOSE 80 creates a mismatch between the documented and actual port
-
Binding Kestrel to localhost (127.0.0.1) inside a Docker container
90% fail
localhost inside a container is only accessible within the container itself; traffic from the Docker network or host port mapping arrives on the container's external interface (0.0.0.0), which localhost binding rejects