How to Build Windows Docker Images with GitHub Actions

How to Build Windows Docker Images with GitHub Actions

Written by Bobby Iliev on Feb 5th, 2025 Views Report Post

Have you ever needed to build a Windows Docker image but don't have access to a Windows machine? In this guide, I'll show you how to leverage GitHub Actions to build Windows container images without needing a local Windows environment.

Why Build Windows Docker Images?

While Linux containers are more common, Windows containers are essential for:

  • .NET Framework applications
  • Windows-specific applications
  • Legacy Windows applications that need containerization
  • Applications that require Windows-specific features

Prerequisites

Before we start, you'll need:

You can take a look at my example repository for reference.

The Dockerfile

Let's look at a sample Dockerfile that sets up a Python environment on Windows:

# Use a more recent Windows Server Core image
FROM mcr.microsoft.com/windows/servercore:ltsc2022

# Set shell to PowerShell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

# Download and install Python
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; \
    Invoke-WebRequest -Uri https://www.python.org/ftp/python/3.9.5/python-3.9.5-amd64.exe -OutFile python-3.9.5-amd64.exe ; \
    Start-Process python-3.9.5-amd64.exe -ArgumentList '/quiet InstallAllUsers=1 PrependPath=1' -Wait ; \
    Remove-Item python-3.9.5-amd64.exe

# Verify Python installation
RUN python --version

# Set the working directory
WORKDIR /app

# Copy application files
COPY . /app

# Set the startup command
CMD ["python", "app.py"]

This Dockerfile:

  • Uses the mcr.microsoft.com/windows/servercore:ltsc2022 base image
  • Installs Python 3.9.5
  • Sets the working directory to /app
  • Copies the application files to the container
  • Specifies the startup command as python app.py

Setting Up GitHub Actions

Create a .github/workflows/build.yml file in your repository:

name: Build Windows Docker Image

on:
  push:
    branches: [ main ]
  workflow_dispatch:

jobs:
  build:
    runs-on: windows-latest
    environment: prod
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and Push
        shell: powershell
        run: |
          docker build . -t ${{ secrets.DOCKERHUB_USERNAME }}/windows-python:latest
          docker push ${{ secrets.DOCKERHUB_USERNAME }}/windows-python:latest

How It Works

  1. The workflow runs on windows-latest runner provided by GitHub Actions
  2. It checks out your code
  3. Logs into Docker Hub using your credentials
  4. Builds the Windows Docker image
  5. Pushes the image to Docker Hub
  6. Displays the image digest for verification

Note that in this example, for simplicity, we're using the latest tag. In a production environment, you should use versioned tags and instead of hardcoding the image name, you can use environment variables.

Important Considerations

  1. Image Size: Windows containers are typically larger than Linux containers. Plan your registry storage accordingly.
  2. Build Time: Windows container builds usually take longer than Linux builds.
  3. Compatibility: Ensure your base image version matches your deployment environment.

Resources

Want to learn more about Docker? Check out these resources:

Conclusion

GitHub Actions makes it possible to build Windows Docker images without a local Windows environment. This approach is particularly useful for cross-platform teams or developers primarily working on non-Windows systems.

If you're new to Docker and want to learn more, I've written a comprehensive free Docker eBook that covers all the basics and more.

Want to try this out but don't have a server? You can use my DigitalOcean referral link to get a free $200 credit!

Have questions or want to share your experience? Feel free to reach out to me on Twitter @bobbyiliev_.

Comments (0)