title: How can I connect to remote systems using PowerShell inside a Nano Server Docker container, specifically build 1809?
body: <p><strong>Background</strong></p>
  
  <p>I have a .NET application that I would like to install inside a Nano Server Docker container, specifically build 1809.  The app is basically a REST server which will receive a REST request and depending on the contents of the JSON, invoke a particular PowerShell cmdlet on a particular remote system and return the results in JSON format.</p>
  
  <p>I was able to create a Nano Server Docker container with both PowerShell and .NET Core installed.  However, I ultimately realized that there is no WinRM installed on the container and therefore it is impossible to invoke remote PowerShell cmdlets.</p>
  
  <p>My host system is Windows Server 2019 Datacenter, Version 1809 (OS Build 17763.379).  I am using Docker Desktop for Windows (Version 2.0.0.3) with Windows containers enabled.</p>
  
  <p><strong>Dockerfile</strong></p>
  
  <p>Here is the Dockerfile I am using.  I created it by combining portions of the Dockerfile from <a href="https://github.com/PowerShell/PowerShell-Docker/blob/master/release/stable/nanoserver1809/docker/Dockerfile" rel="nofollow noreferrer">here</a> and <a href="https://github.com/dotnet/dotnet-docker/blob/master/2.2/sdk/nanoserver-1809/amd64/Dockerfile" rel="nofollow noreferrer">here</a>.</p>
  
  <pre><code># 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 &gt; $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"]
  </code></pre>
  
  <p><strong>Docker Commands</strong></p>
  
  <p>Here are the Docker commands I am using to create and access the Docker container (note the directory contains a single Dockerfile with the contents above):</p>
  
  <pre><code>docker build C:\powershell-nanoserver1809-with-dotnet-2.2.401
  docker create -t --name NanoServerHelloWorld -h NanoServer -i &lt;ID_RETURNED_FROM_PREVIOUS_COMMAND&gt;
  docker start -i NanoServerHelloWorld
  </code></pre>
  
  <p><strong>PowerShell and WinRM commands that fail</strong></p>
  
  <p>On other systems I can use the following PowerShell code to create a CimSession to a remote system and subsequently invoke a PowerShell cmdlet:</p>
  
  <pre><code>$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
  </code></pre>
  
  <p>But in this container I get this error message:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Further, if I try to configure WinRM in anyway, I get the following (from cmd):</p>
  
  <pre><code>C:\&gt;winrm set winrm/config/client @{TrustedHosts="*"}
  'winrm' is not recognized as an internal or external command,
  operable program or batch file.
  </code></pre>
  
  <p>Also, if I look at services on the container, I don't see WinRM:</p>
  
  <pre><code>PS C:\&gt; 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
  </code></pre>
  
  <p><strong>Question</strong></p>
  
  <p>Is there a way to get WinRM installed and working on a Nano Server Docker container build 1809?  If not, is there some workaround to connect to remote systems with PowerShell to invoke PowerShell cmdlets?</p>
  
  <p>Perhaps there is some special Docker command I am missing, or some other Nano Server image available which has this missing feature?</p>
  
  <p>Thanks very much in advance.</p>