'Docker Desktop for Windows: cannot access service on exposed port in windows container mode
I am using the following Dockerfiles to create a container running Jenkins in a windows container on Windows 10 desktop running Docker Desktop for Windows version 17.03
FROM microsoft/windowsservercore
RUN powershell -Command wget 'http://javadl.oracle.com/webapps/download/AutoDL?BundleId=210185' -Outfile 'C:\jreinstaller.exe' ; Start-Process -filepath C:\jreinstaller.exe -passthru -wait -argumentlist "/s,INSTALLDIR=c:\Java\jre1.8.0_91" ; del C:\jreinstaller.exe
ENV JAVA_HOME c:\\Java\\jre1.8.0_91
RUN setx PATH %PATH%;%JAVA_HOME%\bin
CMD [ "java.exe" ]
I create the image from this docker file:
docker build -t windows-java:jre1.8.0_91 .
The second Dockerfile I am using to install Jenkins on top of this:
FROM windows-java:jre1.8.0_91
ENV HOME /jenkins
ENV JENKINS_VERSION 2.58
RUN mkdir \jenkins
RUN powershell -Command "wget -Uri https://updates.jenkins-ci.org/latest/jenkins.war -UseBasicParsing -OutFile /jenkins/jenkins.war"
EXPOSE 8080
EXPOSE 50000
CMD java -jar C:\\jenkins\\jenkins.war
docker build -t jenkins-windows:2.0 .
Then I launch the container like this:
docker run --name jenkinsci -p 8080:8080 -p 50000:50000 jenkins-windows:2.0
I can see the container running fine and logs showing up all good
PS C:\Users\mandeep\ringba\ringba-jenkins-setup-windows\jenkins-master> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85ba2ef525a1 jenkins-windows:2.0 "cmd /S /C 'java -..." 8 hours ago Up 8 hours 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp jenkinsci
However, I cannot access the jenkins server running on http://localhost:8080 on the host machine's web browser.
Not sure if it helps but when I was running docker in Linux container mode on the same machine, I was able to access jenkins server on http://localhost:8080
using their official docker image.
Solution 1:[1]
To complete @Kallie-Microsoft post:
docs.docker.com have been updated with a section Limitations of Windows containers for localhost and published ports
Docker for Windows provides the option to switch Windows and Linux containers. If you are using Windows containers, keep in mind that there are some limitations with regard to networking due to the current implementation of Windows NAT (WinNAT). These limitations may potentially resolve as the Windows containers project evolves.
One thing you may encounter rather immediately is that published ports on Windows containers do not do loopback to the local host. Instead, container endpoints are only reachable from the host using the container’s IP and port.
So, in a scenario where you use Docker to pull an image and run a webserver with a command like this:
docker run -d -p 80:80 --name webserver nginxUsing curl http://localhost, or pointing your web browser at http://localhost will not display the nginx web page (as it would do with Linux containers).
In order to reach a Windows container from the local host, you need to specify the IP address and port for the container that is running the service.
You can get the container IP address by using docker inspect with some --format options and the ID or name of the container. For the example above, the command would look like this, using the name we gave to the container (webserver) instead of the container ID:
$ docker inspect \ --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \ webserver
Solution 2:[2]
I faced the same issue, the ordering of docker run command matters.
docker run -p <host port>:<container port> <image> Works
docker run <image> -p <host port>:<container port> Doesn't Work
My setup -
Using Windows 10 , Version 2004 (OS build 19041.329) WSL 2 enabled - https://docs.microsoft.com/en-us/windows/wsl/wsl2-index Ubuntu 18.04 installed from Microsoft store and its enabled in docker.

Solution 3:[3]
The issue here is that "localhost" does not resolve to your container IP address, since it is not running directly on Windows but rather on a Linux virtual machine through WSL. This a known issue with Docker Desktop.
What you must do is bind your local port (on Windows) to the port on WSL.
In Windows Terminal / Powershell :
Fetch the IP address of the Linux virtual machine (Docker Desktop creates a distro called "docker-desktop" in WSL2)
$wsl_ip = (wsl -d "docker-desktop" -- "ifconfig" "eth0" "|" "grep" "inet addr:").trim("").split(":").split()[2]
Bind your local port to the same port on Linux (see Netsh)
netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=$wsl_ip
Solution 4:[4]
Looks this issue does not seem to be so boring as it was. Followings docs at https://docs.docker.com/engine/reference/run/#expose-incoming-ports you can specify an IP address at the host machine where you want container's port(s) to be exposed.
-p=[] : Publish a container's port or a range of ports to the host format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range, for example: -p 1234-1236:1234-1236/tcp When specifying a range for hostPort only, the containerPort must not be a range. In this case, the container port is published somewhere within the specified hostPort range. (e.g., `-p 1234-1236:1234/tcp`) (use 'docker port' to see the actual mapping)
Probably that is 127.0.0.1, and it resolves an issue with access to exposed Docker container port on the Windows system. Just use -p switch with IP address when running container.
docker run --rm -it -p 127.0.0.1:3000:3000 ubuntu:latest
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alexandre Roux |
| Solution 2 | abitcode |
| Solution 3 | Keyvan |
| Solution 4 | Egeshi |
