ASP.NET on Docker Not Serving Web App to Browser

2020-07-11 09:27发布

问题:

I can't get my ASP.NET web application to get served to my browser when the web app is containerized in Docker.

I'm running a Mac, and I've used Visual Studio Code to create an ASP.NET web application. It's a simple, out-of-the-box demo that is based on the yo aspnet "Empty Application." When run "native" (outside of Docker), this application serves a "Hello World!" to http://localhost:5000 just fine. In other words, running dnx web starts the web server (Kestrel) and yeilds:

Hosting environment: Production 
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

This is good. Now enter Docker. I seem to have successfully built a Docker image containing the web application, and when I run the container in Docker, I get the same output from Kestrel. Also good, but, I can no longer load the "Hello World!" page in my browser at http://localhost:5000. Instead, I get a ERR_CONNECTION_REFUSED. This is fairly obviously because due to the Docker "indirection," there is nothing serving directly to port 5000 anymore. In other words, I think there's an incorrect forwarding configuration, or, I think am misunderstanding the addressing.

I believe that port forwarding is involved in this process. In my Dockerfile, I am using an EXPOSE 5000 which I thought would allow me to map my local use of port 5000 to the Docker container's port 5000 using a run command like this:

docker run -i -t -p 5000:5000 container_name

But that's not the case with http://localhost:5000 (ERR_CONNECTION_REFUSED). So it occurred to me that Docker is almost certainly not at localhost. I had noticed when Docker loads, it says:

docker is configured to use the default machine with IP 192.168.99.100

So, I thought I'd try http://192.168.99.100:5000, but again (confusingly?) ERR_CONNECTION_REFUSED. Next, I read an interesting article here and I was able to determine from the suggested command

docker inspect container_name | grep IPAddress

That the container is assigned "IPAddress": "172.17.0.2"

So, I thought I'd try http://172.17.0.2:5000. And now we might actually be getting somewhere, because instead of a ERR_CONNECTION_REFUSED, I instead get a spinning hourglass and a resulting timeout. But still no "Hello World!"

What might I be missing?

回答1:

It turns out that the web application is available at the IP address of the virtual machine 192.168.99.100 as suspected. 172.17.0.2 was clearly some sort of red herring.

The real kicker seems to be that the container's default "internal" IP is 0.0.0.0

Following the excellent advice of this posting, I edited the Dockerfile and specified the following:

ENTRYPOINT ["dnx", "web", "--server.urls", "http://0.0.0.0:5000"]

Because...

This will allow our web application to serve requests that come in from the port forwarding provided by Docker which defaults to 0.0.0.0

The port mapping is crucial to link the host's port to the container's, but the EXPOSE command is apparently redundant. Now, when I run

docker run -i -t -p 80:5000 container_name

I can simply browse to http://192.168.99.100 (port 80 is implicit)

And viola! There's my "Hello World!"



回答2:

Apart from using http://0.0.0.0:5000 you can use http://*.5000

ENTRYPOINT ["dnx", "web", "--server.urls", "http://*:5000"]

or you can include this against the runtimes environment

"commands": {
    "kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://*:5004"
},
    "web": ......

and the entrypoint in the dockerfile can be

ENTRYPOINT ["dnx","-p","project.json","kestrel"]