web-dev-qa-db-ja.com

Windows Server2016でのWindowsコンテナポートバインディングが機能しない

Windows Container on Windows Host(Windows Server 2016 TP4)を実行しています。

コンテナは内部でポート80のIISWebサーバーを実行し、ポート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およびバインドされたポートを介してIISに到達できません 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

コンテナIP( http://172.16.0.2:8 )経由でのみIISデフォルトページに到達できます。

========================= 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経由ではなく、コンテナIP経由でのみIISに到達できます。

Dockerバージョン1.10.0-dev、ビルド18c9fe0を使用しています。

5
Mathias Conradt

Windows ServerTP4の問題のようです。

DockerチームのStefanSchererが、報告された問題に返信しました: https://github.com/docker/docker/issues/21558#issuecomment-202536462

@mathiasconradtの問題を再現できます。先週TP4でvoting-appを試してみましたが、同じ回避策があります。ホストでファイアウォールポートを開き、コンテナーのIPアドレスを使用してWebサーバーのURLを開きます。 TP5で投票アプリをテストするのが待ちきれません。

TP5を待っています...その間、ホストでApachehttpdを使用してポート転送を処理します。

1
Mathias Conradt

注:最後に、これはWindows Server 2016 TP4のバグであり、以下に説明する動作を引き起こします(コメントを参照)。 Docker Daemonがインストールされていると思われますが、代わりにクライアントが使用されているようですが、以下に説明するすべての制限があります。このバグは、将来のTP5で修正される可能性があります。


これは、ホストを介してコンテナに接続できないWindowsでのDocker実装の制限です。

これは、バグレポートに関する同じ質問に対する答えです #15740:Windowsでのポートの露出=?

これを使用している理由は、Linuxではdockerデーモン(およびコンテナー)がLinuxマシン自体で実行されるため、「localhost」はコンテナーが実行されているホストでもあり、ポートがマップされているためです。

Windows(およびOS X)では、dockerデーモンとコンテナーはネイティブに実行できないため、dockerクライアントのみがWindowsマシンで実行され、デーモン(およびコンテナー)はLinuxを実行するVirtualBox仮想マシンで実行されます。

コンテナに接続するには、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

これはバグではなく、ドキュメントで説明されているため、この問題をクローズします。上記の説明がお役に立てば幸いです。

0
harrymc