Korzystam z kontenera Windows na hoście Windows (Windows Server 2016 TP4) .
Kontener powinien uruchamiać serwer internetowy IIS na porcie 80 wewnętrznie, a także chcę powiązać port 80 z hostem , aby móc do niego dotrzeć za pośrednictwem adresu IP / URL hosta.
Postępowałem zgodnie z instrukcjami Microsoft
- https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/inplace_setup i
- https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/manage_powershell, a także
- https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/manage_docker .
Próbowałem obu metod przez Powershell i Docker, aw obu przypadkach powiązanie portu z hostem nie działa.
========================= Podejście Powershell ======================= ===
Wdrażanie hosta kontenera w istniejącym systemie (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!
Przygotowywanie obrazu i kontenera z uruchomionymi usługami IIS (na podstawie obrazu WindowsServerCore)
Są to dokładne kroki opisane w dokumentacji Microsoft pod adresem https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/manage_powershell . Tworzę kontener z WindowsServerCore, instaluję na nim IIS i tworzę z niego nowy obraz, który mogę później wykorzystać ponownie.
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
Teraz mam gotowy kontener IIS, który łączę z „przełącznikiem wirtualnym”.
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
Dodanie reguły mapowania portów i zapory:
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}
Teraz, gdy dodałem mapowanie portów (i regułę zapory ogniowej), powinienem być w stanie uzyskać dostęp do IIS przez mojego hosta. (Dla pewności całkowicie wyłączyłem zaporę na hoście).
Ale powiązanie portu hosta nie działa. Nie mogę dotrzeć do IIS przez adresy IP hosta i związany port przez http: // localhost: 80 / ani http://172.16.0.1:80/, ani 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
Mogę dotrzeć do domyślnej strony IIS tylko przez adres IP kontenera ( http://172.16.0.2:80 ).
========================= Podejście do dokera ======================= ===
Oto moje podejście do zarządzania kontenerem za pomocą Dockera :
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
Na koniec mogę uzyskać dostęp do IIS tylko przez adres IP kontenera, a nie przez adres IP hosta.
Korzystam z Docker w wersji 1.10.0-dev, kompilacja 18c9fe0.
źródło
Odpowiedzi:
Wygląda na problem z Windows Server TP4.
Stefan Scherer z zespołu Docker odpowiedział na mój zgłoszony problem: https://github.com/docker/docker/issues/21558#issuecomment-202536462
Oczekiwanie na TP5 ... tymczasem używam Apache httpd na hoście do obsługi przekierowania portów.
źródło
Uwaga: w końcu stwierdzono, że jest to błąd w systemie Windows Server 2016 TP4, który powoduje zachowanie opisane poniżej (patrz komentarze). Mimo że podobno zainstalowano demona dokującego, wydaje się, że klient jest używany ze wszystkimi ograniczeniami opisanymi poniżej. Ten błąd można naprawić w przyszłym TP5.
Jest to ograniczenie implementacji Dockera w systemie Windows, gdzie nie można połączyć się z kontenerem za pośrednictwem hosta.
To jest odpowiedź na to samo pytanie dotyczące raportu o błędzie # 15740: ekspozycja portu w systemie Windows =? :
źródło