Dockerizing a PowerShell Script

As I mentioned in my previous post, I’m currently in the process of consolidating the array of Raspberry Pi’s I have running around my house by migrating the various workloads running on them to Docker containers running on a single Raspberry Pi 4 that I have.

After my exploits migrating Pi-hole to Docker (which was far simpler than I anticipated!), next up was migrating a PowerShell script that I run every 5 minutes, which checks the speed of my Internet connection using the Speedtest CLI (which is written in Python) and writes the results to a CSV file.

Why do I do this? Check out “The Joys of Unreliable Internet” which explains more!

To Dockerize the script, I needed to find a container image that runs PowerShell which I could install Python on that supported ARM (the CPU that the Pi uses) – it seemed easier doing this than using a Linux image running Python and installing PowerShell. Fortunately, I found this image which was perfect for my needs, the GitHub repo for this image can be found here.

I also needed a way to store the CSV file that the output of the script is written to on the host machine, this was to ensure this persisted and I didn’t lose any of the logging data. For this reason, I needed to use Docker Compose to create the container as this provides the ability to expose a directory on the host machine directly to the container.

Here is my end solution in all it’s glory!

Firstly is the Dockerfile, which pulls this image, installs Python, creates a new directory “/speedtest” and then copies the SpeedTest.ps1 PowerShell script (which you can find here) into this directory and sets this to run on container startup.

You may be wondering why I’m changing the shell (using SHELL), I needed to do this to change the shell from PowerShell so that I could install Python, I then flip back to PowerShell to run the script. I also needed to run “update-ca-certificates –fresh” as I was experiencing some certificate errors that were causing the SpeedTest.ps1 script to fail.


FROM clowa/powershell-core:latest

SHELL ["/bin/sh", "-c"]
RUN apt-get update -y
RUN apt-get install -y python3
RUN apt-get install -y python3-pip
RUN pip3 install speedtest-cli
RUN update-ca-certificates --fresh

SHELL ["pwsh", "-command"]
RUN mkdir speedtest
COPY ./SpeedTest.ps1 /speedtest/SpeedTest.ps1
WORKDIR /speedtest
CMD ["SpeedTest.ps1"]

To map a directory on the host machine to the container, I needed to create the container using Docker Compose (rather than simply using a Dockerfile) and below is the docker-compose.yml file that I created.

This names the container runner and maps “/home/pi/speedtest/logs on the host machine to “/etc/speedtest/logs” within the container and configures the container to restart should the SpeedTest.ps1 script exit using “restart: unless-stopped” restart policy.


    build: ./
      - /home/pi/speedtest/logs:/etc/speedtest/logs
    restart: unless-stopped

Finally, here is the SpeedTest.ps1 script, which executes the speedtest-cli Python script and writes the output to “/etc/speedtest/logs/SpeedTest.csv” within the container, which is mapped to “/home/pi/speedtest/logs/SpeedTest.csv” on the host machine.


$i = 0
while ($i -eq 0)
    $Time = Get-Date
    $SpeedTest = speedtest-cli --simple
    $Time.ToString() + "," + $SpeedTest[0].split(" ")[1] + "," + $SpeedTest[1].split(" ")[1] + "," + $SpeedTest[2].split(" ")[1]  >> "/etc/speedtest/logs/SpeedTest.csv"
    Start-Sleep -Seconds 300

To get this container up and running I created a directory on the host machine “/home/pi/speedtest” and placed the three files within this directory:

  • SpeedTest.ps1
  • Dockerfile
  • docker-compose.yml

I then executed “docker-compose up -d” from within the “/home/pi/speedtest” directory to build, create and start the container, -d runs the container in detached (background) mode rather than interactively.

I then waited a while and checked the SpeedTest.csv log file within “/home/pi/speedtest/logs” to confirm that the script was running!

Result….now on to my next Dockerization project!

The three files used to create this container can be found on GitHub here.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s