Developer Advocate @docker. Microsoft MVP. Pluralsight Author.
Posts my own.

  My Pluralsight Courses
 
 Old blog 
 Speaking
 Books
 Courses
    http://localhost:2368/content/images/2017/03/docker-london-feb2017.jpg

    Published Ports On Windows Containers Don't Do Loopback

    Docker provides network integration between containers and the host, so when the host receives network requests, they can be routed to a container. On the Docker side, the process is the same on Linux and Windows. This command runs a web server container on Linux and publishes one port:

    docker run -d -p 80:80 nginx:alpine  
    

    This will start Nginx, and publish port 80 from the container to port 80 on the host. When the host receives a request on port 80 on any of its network adapters, the request gets forwarded to port 80 in the container. If you do this on Linux you can run curl http://localhost and see the response from the container:

    > curl http://localhost                                         
    <!DOCTYPE html>  
    <html>  
    ...
    

    The Linux networking stack can receive external requests on its network interfaces, and forward them to Docker containers, and it does the same with loopback requests (to localhost or 127.0.0.1) and direct local requests to the container's IP address:

    Docker NAT in Linux

    In the Windows world the loopback side of this doesn't work right now, only the external request routing. The equivalent to run a standard Web server in the Windows world is:

    docker run -d -p 80:80 microsoft/iis  
    

    That starts IIS running in a container and publishes port 80, mapping to port 80 inside the container. But if you browse to http://localhost on the container host, you won't see the site because of a limitation in the default NAT network stack:

    Container endpoints are only reachable from the Windows host using the container's IP and port

    Full details are here - WinNAT Capabilities and Limitations.

    External requests are routed correctly, so from outside the host you can make a request to port 80 and it will be routed to the container, but if you try to access the site from localhost you'll get an error:

    > curl http://localhost
    curl : Unable to connect to the remote server  
    

    To access the site on the Windows Docker host, you need to make the request using the container's IP address - which is the virtual IP address only visible to the host machine (and the port the container exposes if it's different to the published port, which is where the host is listening for external requests):

    Docker NAT in Windows

    You can get the container's IP address with docker inspect:

    docker inspect --format '{{ .NetworkSettings.Networks.nat.IPAddress }}' <container>  
    

    And then you can browse to the site:

    Docker NAT in Windows

    Hopefully this limitation will be addressed soon. You can see it in action on my YouTube video: Windows Containers and Docker: The 101


    Share this article on
    Author image
    Written by Elton Stoneman
    Developer Advocate @docker. Microsoft MVP. Pluralsight Author.