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?
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!"
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"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With