01
Compare the image and the effective listener
Start with the exact old and new image identities and the application’s startup logs. Look for Kestrel’s listening address, then compare it with the container side of the Docker port mapping. A host port mapping forwards traffic; it does not force Kestrel to listen there.
Microsoft changed the default ASP.NET Core HTTP port in its container images from 80 to 8080 starting with .NET 8. This is a documented image-default change, not a rule that every .NET application always listens on 8080. Application configuration can override it.
02
Read the mapping from left to right
A mapping such as 18080:80 forwards host port 18080 to port 80 inside the container. If startup logs show that the application now listens on 8080, the mapping and listener disagree. Publishing 8080 in a Dockerfile without changing the actual runtime mapping does not repair that path.
Inspect only the relevant port configuration rather than dumping every environment variable. Containers often carry connection strings or credentials that do not belong in a debugging transcript. The commands below inspect the mapping and startup logs; replace the container name with your own.
docker port example-dotnet-api
docker logs --tail=80 example-dotnet-api
# Read only the ASP.NET Core listener-related environment names.
docker inspect --format '{{range .Config.Env}}{{println .}}{{end}}' example-dotnet-api | grep -E '^ASPNETCORE_(HTTP_PORTS|HTTPS_PORTS|URLS)='03
Prefer a mapping that matches the chosen nonprivileged listener
When the intended listener is 8080, recreate the container through your normal deployment process with a mapping to that internal port. The example deliberately binds the published port only to host loopback for local testing. It uses your own application image, not an assumed sample endpoint.
Keep startup configuration explicit so the next image change is easy to compare. ASPNETCORE_HTTP_PORTS can express a simple HTTP port list for compatible modern hosting. Review any ASPNETCORE_URLS or explicit Kestrel endpoint configuration as well; multiple competing settings can make the effective listener differ from one environment value.
# Illustrative local run of your own application image.
docker run --rm --name example-dotnet-api -e ASPNETCORE_HTTP_PORTS=8080 -p 127.0.0.1:18080:8080 example-dotnet-api:tested04
Account for older hosting APIs and explicit endpoints
Microsoft notes that applications using the older WebHost.CreateDefaultBuilder API do not respect ASPNETCORE_HTTP_PORTS. In that case, inspect the application’s hosting model and use a supported listener configuration, such as ASPNETCORE_URLS, when appropriate.
If the application configures Kestrel endpoints directly, follow that configuration rather than assuming an environment variable wins. The objective is one understandable runtime contract. Avoid restoring port 80 and elevated privileges merely to preserve a stale mapping when a nonprivileged port meets the requirement.
# Alternative for a hosting setup that uses URL configuration:
# apply only after checking for competing explicit Kestrel endpoints.
docker run --rm -e ASPNETCORE_URLS=http://+:8080 -p 127.0.0.1:18080:8080 example-dotnet-api:tested05
Test the application route, then the deployment route
Send a request to an endpoint that your application actually implements. A 404 from the application demonstrates a responding HTTP server but not a successful business operation. A connection reset or refusal before HTTP should keep attention on the listener and forwarding path.
After local verification, update any service, reverse-proxy, or orchestration target that depends on the internal port. Change only the relevant routing contract and test through the same public or internal route that previously failed. Preserve authentication and TLS behavior rather than bypassing them to make a test green.
06
Retain evidence that the upgrade is now compatible
Record the new image identity, effective listen address, port mapping, and the successful endpoint request. Recreate the container once in a disposable environment to confirm that the fix is configuration rather than a manual action inside a running container.
If the mapping already matches the listener, investigate startup exceptions, protocol mismatch, authentication, application routing, or dependency failures. The .NET 8 default change is a concrete hypothesis to test, not an explanation to impose on every container connectivity failure.
Know the limits
The default-port change began with .NET 8 official ASP.NET Core images. Custom base images, explicit Kestrel endpoints, older hosting APIs, HTTPS listeners, and non-web .NET processes may behave differently. Commands run a local application image and do not modify an existing production service.
Sources & further reading
A technical publication by CoreTrailKit.
Browse all articles