Windows Server 2016 上的 Windows 容器端口绑定不起作用

Windows Server 2016 上的 Windows 容器端口绑定不起作用

我正在运行Windows 容器Windows 主机(Windows Server 2016 TP4)

容器应运行端口 80 上的 IIS Web 服务器我也想将端口 80 绑定到主机,这样我就可以通过主机 IP/URL 访问它。

我按照微软的说明

我尝试了通过 Powershell 和 Docker 的方法,但在这两种情况下,与主机的端口绑定都不起作用。

============================ Powershell 方法 =============================

将容器主机部署到现有系统(Windows Server 2016 TP4)

PS C:> wget -uri https://aka.ms/tp4/Install-ContainerHost -OutFile C:\Install-ContainerHost.ps1

PS C:> powershell.exe -NoProfile C:\Install-ContainerHost.ps1

Querying status of Windows feature: Containers...
Feature Containers is already enabled.
Waiting for Hyper-V Management...
Networking is already configured.  Confirming configuration...
Getting Container OS image (NanoServer) version 10.0.10586.0 from OneGet (this may take a few minutes)...
Container base image install complete.  Querying container images...
OS image (NanoServer) is already installed.
The following images are present on this machine:
    ContainerImage (Name = 'NanoServer') [Publisher = 'CN=Microsoft', Version = '10.0.10586.0']
    ContainerImage (Name = 'WindowsServerCore') [Publisher = 'CN=Microsoft', Version = '10.0.10586.0']

Docker is already installed.
Stopping Docker...
Starting Docker...
Tagging new base image (8572198a60f1)...
Base image is now tagged:
nanoserver          10.0.10586.0        8572198a60f1        5 months ago        0 B
nanoserver          latest              8572198a60f1        5 months ago        0 B
Script complete!

准备运行 IIS 的镜像和容器(基于 WindowsServerCore 镜像)

这些是 Microsoft 文档中描述的确切步骤https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/manage_powershell。我从 WindowsServerCore 创建一个容器,在其上安装 IIS,并用它创建一个新映像,然后可以重复使用。

PS C:> Get-ContainerImage

Name              Publisher    Version      IsOSImage
----              ---------    -------      ---------
NanoServer        CN=Microsoft 10.0.10586.0 True
WindowsServerCore CN=Microsoft 10.0.10586.0 True


PS C:\> New-Container -Name TP4Demo -ContainerImageName WindowsServerCore -SwitchName "Virtual Switch"

Name    State Uptime   ParentImageName
----    ----- ------   ---------------
TP4Demo Off   00:00:00 WindowsServerCore


PS C:\> Get-Container

Name    State Uptime   ParentImageName
----    ----- ------   ---------------
TP4Demo Off   00:00:00 WindowsServerCore


PS C:\> Start-Container -Name TP4Demo

PS C:\> Enter-PSSession -ContainerName TP4Demo -RunAsAdministrator
[TP4Demo]: PS C:\Windows\system32> Install-WindowsFeature web-server

Success Restart Needed Exit Code      Feature Result
------- -------------- ---------      --------------
True    No             Success        {Common HTTP Features, Default Document, D...


[TP4Demo]: PS C:\Windows\system32> exit
PS C:\> Stop-Container -Name TP4Demo

PS C:\> New-ContainerImage -ContainerName TP4Demo -Name WindowsServerCoreIIS -Publisher Demo -Version 1.0

Name                 Publisher Version IsOSImage
----                 --------- ------- ---------
WindowsServerCoreIIS CN=Demo   1.0.0.0 False


PS C:\> Remove-Container -Name TP4Demo -Force

现在我已经准备好一个 IIS 容器,并将其绑定到“虚拟交换机”。

PS C:\> New-Container -Name IIS -ContainerImageName WindowsServerCoreIIS -SwitchName "Virtual Switch"

Name State Uptime   ParentImageName
---- ----- ------   ---------------
IIS  Off   00:00:00 WindowsServerCoreIIS


PS C:\> Start-Container -Name IIS

PS C:\> Invoke-Command -ContainerName IIS {ipconfig}

Windows IP Configuration

Ethernet adapter vEthernet (Virtual Switch-30179F35-A9BD-4231-B264-BDD2994BD956-0):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::24f4:c726:ed9b:e603%28
   IPv4 Address. . . . . . . . . . . : 172.16.0.2
   Subnet Mask . . . . . . . . . . . : 255.240.0.0
   Default Gateway . . . . . . . . . : 172.16.0.1

添加端口映射和防火墙规则:

PS C:\> if (!(Get-NetNatStaticMapping | where {$_.ExternalPort -eq 80})) {Add-NetNatStaticMapping -NatName "ContainerNat" -Protocol TCP -ExternalIPAddress 0.0.0.0 -InternalIPAddress 172.16.0.2 -InternalPort 80 -ExternalPort 80}

PS C:\> if (!(Get-NetFirewallRule | where {$_.Name -eq "TCP80"})) {New-NetFirewallRule -Name "TCP80" -DisplayName "HTTP on TCP/80" -Protocol tcp -LocalPort 80 -Action Allow -Enabled True}

现在我添加了端口映射(和防火墙规则),我应该能够通过主机访问 IIS。(为了确保万无一失,我完全禁用了主机上的防火墙。)

但主机端口绑定不起作用。我无法通过主机 IP 和绑定端口访问 IIShttp://本地主机:80/也不http://172.16.0.1:80/也不http://10.10.0.79:80/

PS C:\> wget http://10.10.0.79:80/
wget : Unable to connect to the remote server
At line:1 char:1
+ wget http://10.10.0.79:80/
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

PS C:\> wget http://172.16.0.1:80/
wget : Unable to connect to the remote server
At line:1 char:1
+ wget http://172.16.0.1:80/
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

我只能通过容器 IP 访问 IIS 默认页面(http://172.16.0.2:80)。

============================ Docker 方法 =============================

这是我的使用 Docker 的方法管理容器:

C:\> docker run --name iisbase -it windowsservercore cmd
C:\> powershell.exe Install-WindowsFeature web-server
C:\> exit
PS C:\Windows\system32> docker commit iisbase windowsservercoreiis
64271b60a1c4af29ce37ebcee45b00d824883eb67c717d4cee765d9f696867bb
C:\> powershell.exe "if(!(Get-NetFirewallRule | where {$_.Name -eq 'TCP80'})) { New-NetFirewallRule -Name 'TCP80' -DisplayName 'HTTP on TCP/80' -Protocol tcp -LocalPort 80 -Action Allow -Enabled True }"
C:\> docker run --name iisdemo -it -p 80:80 windowsservercoreiis cmd

最后,我只能通过容器 IP 访问 IIS,而不能通过主机 IP 访问。

我正在使用 Docker 版本 1.10.0-dev,构建 18c9fe0。

答案1

似乎是 Windows Server TP4 的一个问题。

Docker 团队的 Stefan Scherer 回复了我报告的问题: https://github.com/docker/docker/issues/21558#issuecomment-202536462

我可以重现@mathiasconradt 的问题。上周在 TP4 上玩了投票应用程序,我使用了相同的解决方法:在主机上打开防火墙端口,使用容器的 IP 地址打开 Web 服务器 URL。迫不及待地想在 TP5 上测试投票应用程序。

等待 TP5...同时我在主机上使用 Apache httpd 来处理端口转发。

答案2

注意:最后发现这是 Windows Server 2016 TP4 中的一个错误,它会导致下面描述的行为(参见注释)。即使应该安装了 Docker Daemon,但似乎还是使用了客户端,并存在下面描述的所有限制。这个错误可能会在未来的 TP5 中得到修复。


这是 Docker 在 Windows 上实现的限制,您无法通过主机连接到容器。

这是错误报告中同一问题的答案 #15740:Windows 上的端口暴露 =?

您遇到这种情况的原因是因为在 Linux 上,docker 守护程序(和您的容器)在 Linux 机器本身上运行,因此“localhost”也是容器运行的主机,并且端口映射到该主机。

在 Windows(和 OS X)上,docker 守护程序和您的容器无法本地运行,因此只有 docker 客户端在您的 Windows 机器上运行,但守护程序(和您的容器)在运行 Linux 的 VirtualBox 虚拟机中运行。

要连接到容器,您必须连接到虚拟机的 IP 地址,而不是 Windows 计算机的 IP 地址。

这一切都在 Windows 安装文档中描述,可以在这里找到; http://docs.docker.com/installation/windows/

本节描述虚拟机;
http://docs.docker.com/installation/windows/#learn-the-key-concepts-before-installing

这里解释了如何映射端口以及如何连接到它们;
http://docs.docker.com/installation/windows/#container-port-redirection

我要关闭这个问题了,因为这不是 bug,文档里也有解释。希望以上解释对你有帮助。

相关内容