Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to install Powershell Core in aspnet Nanoserver docker container?

Is it possible somehow to add Powershell Core to the AspNet Nano Server base images?

We use a multistage dockerfile to produce an image containing our .net core web application. The final image is based on mcr.microsoft.com/dotnet/core/aspnet:3.1-nanoserver-1809 with our .net core binaries added (in order to keep image size to a minimum).

We would like Powershell Core to be included in the final image, for initialization and debugging purposes, but haven't found a way so far. We have considered all sorts of commandline installation options (msiexec, choco and googled a lot) without finding a solution.

Any help is very much appreciated!

like image 729
HVL71 Avatar asked Dec 02 '20 08:12

HVL71


People also ask

Does Nanoserver have PowerShell?

PowerShell, WMI, and the Windows servicing stack are absent from the Nanoserver image.

Can ASP NET application be run in Docker container?

Choose the docker option to run the application as shown in the following image. After clicking on the docker option, it will build code, create a docker image as well as a docker container and run the application inside the docker container without using the docker commands on the windows command prompt.


Video Answer


1 Answers

From Microsoft:

PowerShell Core, .NET Core, and WMI are no longer included by default, but you can include PowerShell Core and .NET Core container packages when building your container.

Although there is no official powershell core support for aspnet:3.1-nanoserver-1809, there is an official powershell core support for pure nanoserver-18.09, see this with the image tag: lts-nanoserver-1809

So, the last thing you need to do is:

Just follow microsoft's suggestion to include powershell core when build your own image.

Next is the Dockerfile about how nanoserver-18.09 to include powershell core, you could copy this to write your own dockerfile to add powershell core to your aspnet:3.1-nanoserver-1809:

# escape=`
# Args used by from statements must be defined here:
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=7.0.0-rc.1

ARG PS_PACKAGE_URL=https://github.com/PowerShell/PowerShell/releases/download/v$PS_VERSION/PowerShell-$PS_VERSION-win-x64.zip

# disable telemetry
ENV POWERSHELL_TELEMETRY_OPTOUT="1"

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

# Install PowerShell into NanoServer
FROM ${NanoServerRepo}:1809

ARG IMAGE_NAME=mcr.microsoft.com/powershell

# Copy PowerShell Core from the installer container
ENV ProgramFiles="C:\Program Files" `
    # set a fixed location for the Module analysis cache
    PSModuleAnalysisCachePath="C:\Users\Public\AppData\Local\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" `
    POWERSHELL_DISTRIBUTION_CHANNEL="PSDocker-NanoServer-1809"

### Begin workaround ###
# Note that changing user on nanoserver is not recommended
# See, https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-base-images#base-image-differences
# But we are working around a bug introduced in the nanoserver image introduced in 1809
# Without this, PowerShell Direct will fail
# this command sholud be like this: https://github.com/PowerShell/PowerShell-Docker/blob/f81009c42c96af46aef81eb1515efae0ef29ad5f/release/preview/nanoserver/docker/Dockerfile#L76
USER ContainerAdministrator

# This is basically the correct code except for the /M
RUN setx PATH "%PATH%;%ProgramFiles%\PowerShell;" /M

USER ContainerUser
### End workaround ###

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 ; `
          }"

# re-enable telemetry
ENV POWERSHELL_TELEMETRY_OPTOUT="0"

CMD ["pwsh.exe"]
like image 67
atline Avatar answered Sep 25 '22 06:09

atline