I'd like to dockerize a simple ASP.net Core Web App which hosts a REST API using Kestrel.
As you can see in the console output, the app works perfectly fine when I run it on my local machine. I see the URLs which it's listening on as well as the endpoint which I called to ensure that it runs correctly:
> dotnet DockerTest.dll
> Hosting environment: Production
> Now listening on: https://localhost:5001
> Now listening on: http://localhost:5000
> Application started. Press Ctrl+C to shut down.
> info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/values
...
My Dockerfile is quite simple. I pull the ASP.net Core base image, copy the output from dotnet publish "DockerTest.csproj" -c Release -o ./output
and execute it just like I executed it on my local machine:
Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY ./output .
ENTRYPOINT ["dotnet", "DockerTest.dll"]
After building the image with docker build -t dockertest .
, I use port binding as well as the ASPNETCORE_URLS
environment variable to let it run on http://localhost:5000
to resemble my local settings:
docker run -p 5000:5000 -e ASPNETCORE_URLS="http://localhost:5000" dockertest
The container's output indicates that the app is listening on http://localhost:5000
:
> Hosting environment: Production
> Content root path: C:\app
> Now listening on: http://localhost:5000
> Application started. Press Ctrl+C to shut down.
But when I try to access the endpoint, I get a timeout and the container never receives the request!
Your problem is caused by the way you specify the ASPNETCORE_URLS
. Instead of binding to localhost
, you should listen on all network interfaces in order to receive requests coming from outside the container.
This can be done by listening on 0.0.0.0
instead of localhost, or by using a wildcard, e.g.:
docker run -p 5000:5000 -e ASPNETCORE_URLS="http://+:5000"
In case of HTTP and HTTPS support:
docker run -p 5000:5000 -p 5001:5001 -e ASPNETCORE_URLS="http://+:5000;https://+:5001"
Or when using the default ports:
docker run -p 5000:80 -p 5001:443 -e ASPNETCORE_URLS="https://+;http://+"
My preferred approach is to use wildcard URLs and overwrite the port via an explicit environment variable when necessary, e.g.:
-p 5000:80 -p 5001:5001 -e ASPNETCORE_URLS="https://+;http://+" -e ASPNETCORE_HTTPS_PORT=5001