简体   繁体   English

"Docker Desktop for Windows:在 Windows 容器模式下无法访问暴露端口上的服务"

[英]Docker Desktop for Windows: cannot access service on exposed port in windows container mode

I am using the following Dockerfiles<\/strong> to create a container running Jenkins in a windows container on Windows 10 desktop running Docker Desktop for Windows<\/strong> version 17.03我正在使用以下Dockerfiles<\/strong>在运行Docker Desktop for Windows<\/strong>版本 17.03 的 Windows 10 桌面上的 Windows 容器中创建运行 Jenkins 的容器

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" ]

This is a currently a known issue on Windows.这是当前 Windows 上的一个已知问题。 It's not possible to access a container endpoint from its own host using localhost/127.0.0.1.无法使用 localhost/127.0.0.1 从其自己的主机访问容器端点。 It is possible using Linux containers today because Docker has included a special workaround that is unique to their Moby/Linux implementation for running Linux containers on Windows.今天可以使用 Linux 容器,因为 Docker 已经包含了一个特殊的解决方法,这是他们在 Windows 上运行 Linux 容器的 Moby/Linux 实现所独有的。

We're working on a fix for this, but today we recommend working around this by either:我们正在为此进行修复,但今天我们建议通过以下任一方式解决此问题:

  • Accessing container endpoints from a separate host , using the IP address of the host that is running the container, and the exposed port for the container on its host单独的主机访问容器端点,使用运行容器的主机的 IP 地址,以及容器在其主机上的公开端口
  • OR by accessing the container on the same host , using the container's internal IP address and published port (you can use docker network inspect <network name> or docker exec <container ID> ipconfig> to get the IP address of the container endpoint itself)或者通过访问同一主机上容器,使用容器的内部 IP 地址和发布的端口(您可以使用docker network inspect <network name>docker exec <container ID> ipconfig>来获取容器端点本身的 IP 地址)

To complete @Kallie-Microsoft post:要完成@Kallie-Microsoft 帖子:

docs.docker.com have been updated with a section Limitations of Windows containers for localhost and published ports docs.docker.com 已更新为本地主机和已发布端口的 Windows 容器限制部分


Docker for Windows provides the option to switch Windows and Linux containers. Docker for Windows 提供了切换 Windows 和 Linux 容器的选项。 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).如果您使用的是 Windows 容器,请记住,由于 Windows NAT (WinNAT) 的当前实现,在网络方面存在一些限制。 These limitations may potentially resolve as the Windows containers project evolves.随着 Windows 容器项目的发展,这些限制可能会得到解决。

One thing you may encounter rather immediately is that published ports on Windows containers do not do loopback to the local host.您可能会立即遇到的一件事是,Windows 容器上的已发布端口不会回环到本地主机。 Instead, container endpoints are only reachable from the host using the container's IP and port.相反,容器端点只能从主机使用容器的 IP 和端口访问。

So, in a scenario where you use Docker to pull an image and run a webserver with a command like this:因此,在使用 Docker 拉取映像并使用如下命令运行网络服务器的场景中:

 docker run -d -p 80:80 --name webserver nginx

Using 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).使用 curl http://localhost或将 Web 浏览器指向http://localhost将不会显示 nginx 网页(就像使用 Linux 容器一样)。

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.为了从本地主机访问 Windows 容器,您需要为运行服务的容器指定 IP 地址和端口。

You can get the container IP address by using docker inspect with some --format options and the ID or name of the container.您可以通过使用 docker inspect 和一些 --format 选项以及容器的 ID 或名称来获取容器 IP 地址。 For the example above, the command would look like this, using the name we gave to the container (webserver) instead of the container ID:对于上面的示例,命令看起来像这样,使用我们为容器(网络服务器)提供的名称而不是容器 ID:

 $ docker inspect \\ --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \\ webserver

I faced the same issue, the ordering of docker run command matters.我遇到了同样的问题, docker run 命令的顺序很重要。

docker run -p <host port>:<container port> <image> Works docker run -p <host port>:<container port> <image>作品

docker run <image> -p <host port>:<container port> Doesn't Work docker run <image> -p <host port>:<container port>不起作用

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.使用 Windows 10 2004 版(操作系统版本 19041.329)启用 WSL 2 - https://docs.microsoft.com/en-us/windows/wsl/wsl2-index从 Microsoft 商店安装的 Ubuntu 18.04 并在 docker 中启用。

图片

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.这里的问题是“localhost”无法解析到您的容器 IP 地址,因为它不是直接在 Windows 上运行,而是通过 WSL 在 Linux 虚拟机上运行。 This a known issue with Docker Desktop .这是Docker Desktop 的一个已知问题

What you must do is bind your local port (on Windows) to the port on WSL.您必须做的是将本地端口(在 Windows 上)绑定到 WSL 上的端口。

In Windows Terminal / Powershell :在 Windows 终端/Powershell 中:

Fetch the IP address of the Linux virtual machine (Docker Desktop creates a distro called "docker-desktop" in WSL2)获取 Linux 虚拟机的 IP 地址(Docker Desktop 在 WSL2 中创建了一个名为“docker-desktop”的发行版)

$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 )将本地端口绑定到 Linux 上的同一端口(请参阅Netsh

netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=$wsl_ip

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.以下文档位于https://docs.docker.com/engine/reference/run/#expose-incoming-ports,您可以在要公开容器端口的主机上指定 IP 地址。

 -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. (eg, `-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.可能是 127.0.0.1,它解决了访问 Windows 系统上暴露的 Docker 容器端口的问题。 Just use -p switch with IP address when running container.运行容器时,只需使用带有 IP 地址的 -p 开关即可。

docker run --rm -it -p 127.0.0.1:3000:3000 ubuntu:latest

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM