How to run PowerShell in Docker with custom modules

Sypalo.com

The idea of launching PowerCLI with the necessary modules in the Docker container has long been brewing, and finally I have taken up this issue.

One of the reasons was that PowerShell “broke down” on my Windows 10 machine, or rather, it works, but the Get-Credential command returns an error. The second reason is simply the desire to experiment on the topic.

It turned out the truth is not so simple, details below. To run PowerShell in a Docker container with pre-loaded modules, you need to perform the following steps:

  1. Enable Virtualization Support in BIOS
  2. Install Hyper-V, you can do it like this:
  3. Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
    or so:
    DISM /Online /Enable-Feature /All /FeatureName: Microsoft-Hyper-V
  4. Install Docker Desktop for Windows
  5. Create an empty folder, say D:\powershell-docker
  6. Add the required modules to the subfolder D:\powershell-docker\Modules
  7. Create a Dockerfile in D:\powershell-docker as follows
    # Use an existing docker image as a base 
    FROM mcr.microsoft.com/powershell

    # Copy Cisco UCS Power Tools to the standard modules location
    COPY ./Modules ./usr/local/share/powershell/Modules

    # Create a path in advance, then add required path to the file
    RUN mkdir -p /root/.config/powershell/RUN echo `Import-Module Cisco.UCSManager`> /root/.config/powershell/Microsoft.PowerShell_profile.ps1
  8. Open CMD or PowerShell and go to D:\powershell-docker
  9. Run the docker build -t powershell-docker command
  10. Start our container: docker run -it powershell-docker

The main problem was that when PowerShell Core started a container, it created a new session and importing modules via ENTRYPOINT or CMD did not lead to anything, the modules were accessible via Get-Module -ListAvailable, but they had to be imported manually, because autoloading does not work when using commands from available but not imported modules.

Another oddity/bug found is that the $profile variable (if you just see the value of this variable in a container running PowerShell Core points to the path /root/.config/powershell/Microsoft.PowerShell_profile.ps1, but this file does not exist.

As I said above, it does not make sense to redefine a profile, since at the start of a new session, $profile will again point to the same. Therefore, as an option to create this path and file and specify in it the list of modules to import, which was done above in the Dockerfile.

I hope the information was useful, if you have any questions, ask in the comments, and send any code improvements as a pull request to the github, where the source code is posted.