如何在Nano Server Docker容器(特别是内部版本1809)中使用PowerShell连接到远程系统?

时间:2019-07-29 18:43:18

标签: powershell docker dockerfile powershell-remoting nano-server

背景

我有一个.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。我是通过结合来自herehere的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映像吗?

非常感谢。

0 个答案:

没有答案