5

Я использую контейнер Windows на хосте Windows (Windows Server 2016 TP4).

Контейнер должен запускать веб-сервер IIS на внутреннем порту 80, и я также хочу привязать порт 80 к хосту, чтобы я мог связаться с ним через IP/URL хоста.

Я следовал инструкциям от Microsoft на

Я попробовал оба подхода через 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 через мой хост. (Просто чтобы быть уверенным, я полностью отключил брандмауэр на хосте.)

Но привязка порта хоста не работает. Я не могу связаться с IIS через IP-адреса хоста и связанный порт через http://localhost: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

Я могу получить доступ к странице по умолчанию IIS только через IP-адрес контейнера (http://172.16.0.2:80).

========================= Докер подход ======================= ===

И это мой подход с использованием 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

В конце концов, я могу достичь IIS только через IP-адрес контейнера, а не через IP-адрес хоста.

Я использую Docker версии 1.10.0-dev, сборка 18c9fe0.

2 ответа2

1

Кажется, проблема с Windows Server TP4.

Стефан Шерер из команды Docker ответил на мою проблему:https://github.com/docker/docker/issues/21558#issuecomment-202536462

Я могу воспроизвести проблемы @mathiasconradt. Играл с приложением для голосования на прошлой неделе с TP4, у меня есть тот же обходной путь: открытие портов брандмауэра на хосте, открытие URL веб-сервера с IP-адресами контейнера. Не могу дождаться, чтобы проверить приложение для голосования на TP5.

В ожидании TP5 ... тем временем я использую Apache httpd на хосте для обработки переадресации портов.

0

Примечание. Наконец, в Windows Server 2016 TP4 обнаружена ошибка, которая вызывает поведение, описанное ниже (см. Комментарии). Несмотря на то, что Docker Daemon предположительно установлен, кажется, что вместо этого используется клиент со всеми ограничениями, описанными ниже. Эта ошибка может быть исправлена в будущем TP5.


Это ограничение реализации Docker в Windows, где вы не можете подключиться к контейнеру через хост.

Это ответ на этот же вопрос в отчете об ошибке № 15740: экспозиция порта в windows =? :

Причина этого заключается в том, что в Linux демон docker (и ваши контейнеры) работают на самой машине Linux, поэтому "localhost" также является хостом, на котором работает контейнер, и порты отображаются на него.

В Windows (и OS X) демон-докер и ваши контейнеры не могут работать в исходном режиме, поэтому на вашем компьютере с Windows работает только клиент-докер, но демон (и ваши контейнеры) работают на виртуальной машине VirtualBox, на которой работает Linux.

Чтобы подключиться к контейнеру, необходимо подключиться к IP-адресу виртуальной машины, а не вашего компьютера с Windows.

Все это описано в документации по установке 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

Я собираюсь закрыть эту проблему, потому что это не ошибка, и объяснено в документации. Я надеюсь, что приведенное выше объяснение поможет вам.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .