CenturionStudio.it - Fotolia

Combine PowerShell and Docker to simplify testing across OSes

Run PowerShell scripts in Docker containers to manage multiple environments from the same system. Follow this tutorial to see how to test Linux environments with a Windows host OS.

PowerShell's scope has expanded greatly over the years. Once exclusively used in Windows environments, the command-line interface now runs on any major operating system, across platforms and in containers.

Docker containers are among the more intriguing ways to utilize PowerShell today because developers and admins can use the combination to run multiple environments from the same system. In addition to all the normal advantages of running Docker containers, IT pros can use PowerShell in Docker to test scripts across multiple OSes without needing full installations.

Let's take a closer look at how that process might work.

How to run PowerShell in a Docker container

To run PowerShell in a Docker container, you'll first need to install Docker. For the purposes of this tutorial, we'll run through these steps on a Windows 10 x64 computer, with Docker Desktop installed.

With Docker installed, run the following command to pull the Docker image into a local repository:

docker pull mcr.microsoft.com/powershell

The output should look similar to Figure 1.

the output from a Docker repository image pull
Figure 1. Docker repository image pull.

By default, this command will download a specific image, depending on which OS your host system runs -- Windows Server Core for Windows, Ubuntu 18.04 for Linux. However, you can get a particular image if you specify a tag. For instance, to get Ubuntu 18.04 with PowerShell, run the following command:

docker pull mcr.microsoft.com/powershell:ubuntu-18.04

This will result in an output that looks like the one in Figure 2.

using a tag to get Ubuntu 18.04 with PowerShell
Figure 2. Request Ubuntu 18.04 with PowerShell.

With the image downloaded, run an interactive version of the PowerShell Docker container with the following command:

docker run -it mcr.microsoft.com/powershell:ubuntu-18.04

The output should look similar to Figure 3.

running a PowerShell Docker container
Figure 3. Run PowerShell Docker container.

Then, verify that you are indeed running on Linux with the following command:

$PSVersionTable

The output will contain "Linux" in the OS string, as seen in Figure 4.

PSVersionTable output that verifies Linux is running
Figure 4. PSVersionTable output.

By running PowerShell in Docker, you have access to versions and OSes not on your host machine. As a result, you can test scripts in many environments without having to spin up full virtual machines.

In this example, a Docker container was launched with PowerShell running on Ubuntu, while the host system was running Windows 10. A Windows admins could use this capability to test their PowerShell scripts and commands on a Linux-based OS. If you check the entire list of tags available, you end up with a huge number of options.

How to run a PowerShell script in a Docker container

To run a PowerShell script on the container, you'll need to create a container with the selected image, copy the script to the container and then run it.

First, write the PowerShell script intended to run in a Docker container. For the sake of simplicity, let's use a basic two-line script that outputs the current PowerShell version and then requests the time for the user's IP address:

$PSVersionTable
Invoke-RestMethod -Uri 'http://worldtimeapi.org/api/ip'

This script is a call to the World Time API.

Then, create a Docker container called "demo" with the following command:

docker create -ti --name demo mcr.microsoft.com/powershell:ubuntu-18.04

And with that container created, copy the script to it with the following command:

docker cp C:\scripts\time.ps1 demo:/root/time.ps1

Notice that the script is copied straight into the root user's profile.

Then, run the Docker container with the following command:

docker start demo

To execute the script, run the following command:

docker exec demo pwsh -command "/root/time.ps1"

This should output the version of PowerShell on my Ubuntu container and the correct time based on the location of the public IP, which is shown in Figure 5.

output showing PowerShell version on Ubuntu container and the time based on public IP location
Figure 5. Ubuntu container PowerShell output.

Why run PowerShell in Docker

As we've discussed, you simplify the testing process across systems when you combine PowerShell and Docker. However, you'll likely need to understand some basic differences between OSes to succeed. Let's run through another example to illustrate this.

Say we have a script that comes with a config file in JSON format. The file contains some configuration data as well as an encrypted authorization token used to authenticate to an API. That setup might look like Figure 6.

PowerShell script and its JSON config file
Figure 6. Created script and its JSON config file.

For simplicity's sake, we'll only include a few lines in the script where we load the config and output its contents:

$config = Get-Content $PSScriptRoot\Config.json | ConvertFrom-Json
Write-Host $config | ConvertTo-Json

If I test this on my Windows 10 computer running PowerShell 7.1.2, this outputs correctly:

Next, let's test this on our Docker container. Here are the commands:

docker cp C:\scripts\TechTarget\script.ps1 demo:/root/script.ps1
docker cp C:\scripts\TechTarget\config.json demo:/root/config.json
docker exec demo pwsh -command "/root/script.ps1"

However, now that the script is running in a Linux environment, it fails even though it's running on the same version of PowerShell.

script failure on Linux because it's case sensitive
Figure 7. Script fails on Linux.

If we run Get-ChildItem on that directory, we see that the config.json file is there.

config.json file
Figure 8. config.json file.

The script couldn't find the config file is because it was looking for Config.json while the file is called config.json. Linux is case sensitive, while Windows is not. Longtime Windows users, like myself, might not immediately catch this.

So, if we fix the script to use the proper case and then update the script file on the Linux container, we should get the expected output seen in Figure 9.

Successful PowerShell script output on Linux container
Figure 9. Successful output on Linux container.

Running PowerShell in a Docker container is like learning how to customize a PowerShell prompt for the first time. You never thought you needed it until you saw that one killer prompt in a PowerShell Summit demo and now you have spent hours figuring yours out.

Now that PowerShell is a cross-platform tool, it pays to understand the differences in how it runs on other OSes. With just a simple Docker container, you can add Linux to your resume and suddenly translate years of Windows Server management into an opportunity to get into the world of Linux.

Dig Deeper on Containers and virtualization