背景
我有一个.NET应用程序,我想安装在Nano Server Docker容器中,特别是内部版本1809。该应用程序基本上是一个REST服务器,它将接收REST请求,并根据JSON的内容调用特定的在特定远程系统上的PowerShell cmdlet,并以JSON格式返回结果。
我能够创建同时安装PowerShell和.NET Core的Nano Server Docker容器。但是,我最终意识到容器上没有安装WinRM,因此不可能调用远程PowerShell cmdlet。
我的主机系统是Windows Server 2019数据中心,版本1809(操作系统内部版本17763.379)。我正在启用Windows容器的情况下使用Windows的Docker桌面(2.0.0.3版)。
Dockerfile
这里是我正在使用的Dockerfile。我通过组合here和here中的Dockerfile部分来创建它。
# escape=` # Args used by from statements must be defined here: ARG fromTag=1809 ARG InstallerVersion=nanoserver ARG InstallerRepo=mcr.microsoft.com/powershell ARG NanoServerRepo=mcr.microsoft.com/windows/nanoserver # Use server core as an installer container to extract PowerShell, # As this is a multi-stage build, this stage will eventually be thrown away FROM ${InstallerRepo}:$InstallerVersion AS installer-env # Arguments for installing PowerShell, must be defined in the container they are used ARG PS_VERSION=6.2.0 ARG PS_PACKAGE_URL=https://github.com/PowerShell/PowerShell/releases/download/v$PS_VERSION/PowerShell-$PS_VERSION-win-x64.zip SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] ARG PS_PACKAGE_URL_BASE64 RUN Write-host "Verifying valid Version..."; ` if (!($env:PS_VERSION -match '^\d+\.\d+\.\d+(-\w+(\.\d+)?)?$' )) { ` throw ('PS_Version ({0}) must match the regex "^\d+\.\d+\.\d+(-\w+(\.\d+)?)?$"' -f $env:PS_VERSION) ` } ` $ProgressPreference = 'SilentlyContinue'; ` if($env:PS_PACKAGE_URL_BASE64){ ` Write-host "decoding: $env:PS_PACKAGE_URL_BASE64" ;` $url = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($env:PS_PACKAGE_URL_BASE64)) ` } else { ` Write-host "using url: $env:PS_PACKAGE_URL" ;` $url = $env:PS_PACKAGE_URL ` } ` Write-host "downloading: $url"; ` [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; ` New-Item -ItemType Directory /installer > $null ; ` Invoke-WebRequest -Uri $url -outfile /installer/powershell.zip -verbose; ` Expand-Archive /installer/powershell.zip -DestinationPath \PowerShell # ------------------------------------------------------------------------------------------------------------------------------------------------------- # Retrieve .NET Core SDK USER ContainerAdministrator ENV DOTNET_SDK_VERSION 2.2.401 RUN Invoke-WebRequest -OutFile dotnet.zip https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$Env:DOTNET_SDK_VERSION/dotnet-sdk-$Env:DOTNET_SDK_VERSION-win-x64.zip; ` $dotnet_sha512 = 'ed83eb5606912cd78d7696fbdc8e8074afa95fda84eec57b078d7371848ad15fe91aaf521b85e77c69b844a7b036a2c0b7b6cac87a8e356643980d96b689af93'; ` if ((Get-FileHash dotnet.zip -Algorithm sha512).Hash -ne $dotnet_sha512) { ` Write-Host 'CHECKSUM VERIFICATION FAILED!'; ` exit 1; ` }; ` ` Expand-Archive dotnet.zip -DestinationPath dotnet; ` Remove-Item -Force dotnet.zip # ------------------------------------------------------------------------------------------------------------------------------------------------------- # Install PowerShell into NanoServer FROM ${NanoServerRepo}:${fromTag} # Copy PowerShell Core from the installer container ENV ProgramFiles="C:\Program Files" ` # set a fixed location for the Module analysis cache LOCALAPPDATA="C:\Users\ContainerAdministrator\AppData\Local" ` PSModuleAnalysisCachePath="$LOCALAPPDATA\Microsoft\Windows\PowerShell\docker\ModuleAnalysisCache" ` # Persist %PSCORE% ENV variable for user convenience PSCORE="$ProgramFiles\PowerShell\pwsh.exe" ` # Set the default windows path so we can use it WindowsPATH="C:\Windows\system32;C:\Windows" # Set the path ENV PATH="$WindowsPATH;C:\Program Files\PowerShell;C:\Program Files\dotnet;" COPY --from=installer-env ["\\PowerShell\\", "$ProgramFiles\\PowerShell"] # intialize powershell module cache RUN pwsh ` -NoLogo ` -NoProfile ` -Command " ` $stopTime = (get-date).AddMinutes(15); ` $ErrorActionPreference = 'Stop' ; ` $ProgressPreference = 'SilentlyContinue' ; ` while(!(Test-Path -Path $env:PSModuleAnalysisCachePath)) { ` Write-Host "'Waiting for $env:PSModuleAnalysisCachePath'" ; ` if((get-date) -gt $stopTime) { throw 'timout expired'} ` Start-Sleep -Seconds 6 ; ` }" # ------------------------------------------------------------------------------------------------------------------------------------------------------- COPY --from=installer-env ["/dotnet", "/Program Files/dotnet"] # ------------------------------------------------------------------------------------------------------------------------------------------------------- USER ContainerAdministrator EXPOSE 80/tcp EXPOSE 5985/tcp EXPOSE 5986/tcp EXPOSE 7777/tcp EXPOSE 7778/tcp CMD ["pwsh.exe"]
Docker命令
这是我用来创建和访问Docker容器的Docker命令(请注意,该目录包含一个包含上面内容的Dockerfile):
docker build C:\powershell-nanoserver1809-with-dotnet-2.2.401 docker create -t --name NanoServerHelloWorld -h NanoServer -i <ID_RETURNED_FROM_PREVIOUS_COMMAND> docker start -i NanoServerHelloWorld
失败的PowerShell和WinRM命令
在其他系统上,我可以使用以下PowerShell代码创建到远程系统的CimSession,然后调用PowerShell cmdlet:
$u = "REMOTE_DOMAIN\REMOTE_USERNAME"; $pw = "REMOTE_PASSWORD"; $secStr = New-Object -TypeName System.Security.SecureString; $pw.ToCharArray() | ForEach-Object {$secStr.AppendChar($_)}; $Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $u, $secStr; $Session = New-CimSession -ComputerName 172.27.0.114 -Authentication Negotiate -Credential $Cred -OperationTimeoutSec 900
但是在此容器中,我收到此错误消息:
New-CimSession : FAILED At line:1 char:12 + $Session = New-CimSession -ComputerName 172.27.0.114 -Authentication ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [New-CimSession], CimException + FullyQualifiedErrorId : Microsoft.Management.Infrastructure.CimException,Microsoft.Management.Infrastructure.CimCmdlets.NewCimSessionCommand
此外,如果我仍然尝试配置WinRM,则会从cmd中获得以下内容:
C:\>winrm set winrm/config/client @{TrustedHosts="*"} 'winrm' is not recognized as an internal or external command, operable program or batch file.
此外,如果我查看容器上的服务,则看不到WinRM:
PS C:\> Get-Service Status Name DisplayName ------ ---- ----------- Running cexecsvc Container Execution Agent Running CryptSvc Cryptographic Services Running DcomLaunch DCOM Server Process Launcher Running Dhcp DHCP Client Running DiagTrack Connected User Experiences and Teleme… Running Dnscache DNS Client Running EventLog Windows Event Log Stopped KeyIso CNG Key Isolation Stopped LanmanServer Server Running LanmanWorkstation Workstation Stopped lmhosts TCP/IP NetBIOS Helper Stopped mpssvc Windows Defender Firewall Stopped Netlogon Netlogon Stopped NetSetupSvc Network Setup Service Running nsi Network Store Interface Service Stopped Power Power Running ProfSvc User Profile Service Running RpcEptMapper RPC Endpoint Mapper Running RpcSs Remote Procedure Call (RPC) Running SamSs Security Accounts Manager Running Schedule Task Scheduler Stopped seclogon Secondary Logon Running SystemEventsBroker System Events Broker Running TimeBrokerSvc Time Broker Get-Service : Service 'TrustedInstaller (TrustedInstaller)' cannot be queried due to the following error: At line:1 char:1 + Get-Service + ~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (System.ServiceProcess.ServiceController:ServiceController) [Get-Service], ServiceCommandException + FullyQualifiedErrorId : CouldNotGetServiceInfo,Microsoft.PowerShell.Commands.GetServiceCommand Stopped TrustedInstaller TrustedInstaller Running UserManager User Manager Stopped VaultSvc Credential Manager Stopped WerSvc Windows Error Reporting Service Stopped WinHttpAutoProxyS… WinHTTP Web Proxy Auto-Discovery Serv… Stopped wisvc Windows Insider Service
问题
是否有安装WinRM并在Nano Server Docker容器内部版本1809上工作的方法?如果没有,是否存在一些解决方法来使用PowerShell连接到远程系统以调用PowerShell cmdlet?
也许我缺少某些特殊的Docker命令,或者其他一些具有此缺失功能的Nano Server可用映像?
非常感谢。
背景我有一个.NET应用程序,我想安装在Nano Server Docker容器内,特别是内部版本1809。该应用程序基本上是一个REST服务器,它将接收REST请求...
您有运气得到这个答案吗?