Introduction
Windows containers bring the containerization model to Windows-native workloads — legacy .NET Framework applications, IIS web servers, Windows services, and COM-dependent applications that cannot run in Linux containers. Windows Server 2022 supports a range of Windows container base images from the Microsoft Container Registry (MCR), each offering a different trade-off between compatibility and image size. This guide covers pulling and working with those base images, writing Dockerfiles for Windows, running IIS in a container, managing volumes and environment variables, understanding Windows container networking modes, and the distinction between process and Hyper-V isolation.
Windows Container Base Images Overview
Microsoft provides four primary base images for Windows containers, all hosted at mcr.microsoft.com:
Windows Server Core (mcr.microsoft.com/windows/servercore) is the workhorse image for most Windows workloads. It includes the majority of the Win32 API surface, supports .NET Framework 3.5 and 4.x, and can run most GUI-less Windows applications. The compressed image size is several gigabytes, making it the largest of the four options. Use it for legacy .NET Framework applications, IIS-hosted ASP.NET apps, and tools that depend on broad Windows API coverage.
Nano Server (mcr.microsoft.com/windows/nanoserver) is the smallest Windows container image. It supports only 64-bit .NET Core (not .NET Framework), does not include PowerShell by default (PowerShell Core can be added), and has a minimal API surface. It is optimized for microservices built on modern .NET.
Windows Server (mcr.microsoft.com/windows/server) is the most complete image, including nearly the full Windows Server API surface. It is substantially larger than Server Core and intended for workloads with the broadest compatibility requirements.
IIS (mcr.microsoft.com/windows/servercore/iis) is a pre-built image layered on Server Core that installs and configures IIS, ready to serve web content.
All production images on Windows Server 2022 should use the ltsc2022 tag to ensure kernel version compatibility with the host:
docker pull mcr.microsoft.com/windows/servercore:ltsc2022
docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022
docker pull mcr.microsoft.com/windows/server:ltsc2022
docker pull mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
Writing a Dockerfile for Windows
Dockerfiles for Windows use the same syntax as Linux Dockerfiles but reference Windows-specific paths and commands. The FROM directive must point to a Windows base image. Shell commands default to cmd unless you switch to PowerShell using SHELL. Here is a minimal Dockerfile that uses Server Core, copies in an application, and sets an entry point:
FROM mcr.microsoft.com/windows/servercore:ltsc2022
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
WORKDIR C:\app
COPY . C:\app
RUN New-Item -ItemType Directory -Force -Path C:\app\logs
EXPOSE 8080
ENTRYPOINT ["powershell", "-File", "C:\app\start.ps1"]
Note the double backslashes in Windows paths when used inside JSON-format instructions (ENTRYPOINT, CMD arrays). Single backslashes work inside RUN cmd /c “…” or within quoted PowerShell strings. Build the image from the directory containing the Dockerfile:
docker build -t mywindowsapp:1.0 .
Running IIS in a Windows Container
The IIS base image is one of the most common production use cases for Windows containers. Pull the image and run it with port mapping to serve traffic from the host:
docker run -d -p 80:80 --name myiis mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
To customise the IIS container — for example to add your application files and configure a site — build a Dockerfile layered on top of the IIS image:
FROM mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
RUN Remove-Website -Name 'Default Web Site'
RUN New-Website -Name 'mysite' -Port 80 -PhysicalPath 'C:inetpubmysite' -ApplicationPool '.NET v4.5'
COPY ./wwwroot C:\inetpub\mysite
EXPOSE 80
Build and run this customised image:
docker build -t myiisapp:1.0 .
docker run -d -p 80:80 --name myiisapp myiisapp:1.0
Browse to http://localhost or the server’s IP address to confirm IIS is serving the site.
Volume Mounts on Windows
Windows containers support bind mounts and named volumes, but use Windows-style paths. The host path must be on the same drive as the container and must exist before the container starts. To mount a host directory into a container, use the -v flag with Windows paths. Note that Docker on Windows requires forward slashes or escaped backslashes in the -v argument:
docker run -d -p 80:80 -v C:inetpubmysite:C:inetpubwwwroot --name iis mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
Named volumes (managed by Docker) work the same way as on Linux:
docker volume create mydata
docker run -d -v mydata:C:appdata --name myapp mywindowsapp:1.0
Inspect a volume to find its location on the host:
docker volume inspect mydata
Windows container volumes are stored under C:ProgramDataDockervolumes by default. Unlike Linux containers, Windows containers cannot mount volumes from Linux hosts and vice versa — volume sharing is limited to the same OS type.
Environment Variables
Pass environment variables into containers at runtime using the -e flag:
docker run -d -e APP_ENV=production -e DB_HOST=sqlserver -e DB_PORT=1433 --name myapp mywindowsapp:1.0
Reference environment variables in a Dockerfile using the ENV instruction:
FROM mcr.microsoft.com/windows/servercore:ltsc2022
ENV APP_PORT=8080
ENV LOG_LEVEL=info
EXPOSE $APP_PORT
Inside a running Windows container, environment variables are accessible to cmd via %VARIABLE% and to PowerShell via $env:VARIABLE. To inspect the environment of a running container from the host:
docker inspect --format "{{range .Config.Env}}{{println .}}{{end}}" myapp
Windows Container Networking Modes
Docker on Windows Server 2022 supports several network drivers specifically designed for Windows containers:
NAT (default) — Each container gets a private IP on an internal network, and outbound traffic is NAT’d through the host’s external IP. Port publishing (-p) creates host-to-container port mappings. This is the simplest mode and suitable for most single-host deployments. Create a NAT network explicitly:
docker network create -d nat --subnet=172.20.0.0/16 mynat
Transparent — Each container gets an IP address directly on the physical network, assigned either statically or via DHCP. Containers appear as peers on the physical LAN. This mode is useful when containers need to be directly reachable without port mapping:
docker network create -d transparent --subnet=192.168.1.0/24 --gateway=192.168.1.1 mytransparent
Overlay — Used in Docker Swarm mode to connect containers across multiple hosts. Requires Swarm to be initialised:
docker swarm init
docker network create -d overlay --attachable myoverlay
To attach a container to a specific network:
docker run -d --network mynat --name myapp mywindowsapp:1.0
Building and Pushing Images to a Registry
Tag your locally built image with a registry path before pushing. This example uses Docker Hub, but the same process applies to Azure Container Registry, AWS ECR, or a private registry:
docker tag mywindowsapp:1.0 myregistry.azurecr.io/mywindowsapp:1.0
Log into the registry:
docker login myregistry.azurecr.io --username myuser --password mypassword
Push the image:
docker push myregistry.azurecr.io/mywindowsapp:1.0
Pull it on another Windows Server 2022 host:
docker pull myregistry.azurecr.io/mywindowsapp:1.0
Note that Windows container images carry the full Windows base image layers and can be several gigabytes in size. Multi-stage builds help reduce final image size by separating build tools from the runtime image:
FROM mcr.microsoft.com/dotnet/sdk:8.0-windowsservercore-ltsc2022 AS build
WORKDIR C:\src
COPY . .
RUN dotnet publish -c Release -o C:\publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0-windowsservercore-ltsc2022
WORKDIR C:\app
COPY --from=build C:\publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Container Isolation Modes: Process vs Hyper-V
Windows containers support two isolation modes that have significant security and compatibility implications:
Process isolation — Containers share the host kernel. The container and host must run the same (or compatible) Windows kernel version. This is the default on Windows Server and provides the highest density and lowest overhead. All containers run using the same kernel, so a privilege escalation in the kernel could affect all containers and the host:
docker run --isolation=process -d mcr.microsoft.com/windows/servercore:ltsc2022 cmd /c ping -t localhost
Hyper-V isolation — Each container runs inside a lightweight Hyper-V virtual machine with its own kernel instance. The container’s kernel version is embedded in the image, meaning you can run older Windows container images on a newer host. The trade-off is higher memory overhead and lower container density. This is the default on Windows 10/11 client and is preferred for multi-tenant environments:
docker run --isolation=hyperv -d mcr.microsoft.com/windows/servercore:ltsc2022 cmd /c ping -t localhost
Check the isolation mode of a running container:
docker inspect --format "{{.HostConfig.Isolation}}" mycontainer
To use Hyper-V isolation on Windows Server 2022, the Hyper-V role must be installed and the server must support hardware virtualisation (nested virtualisation if running in a VM):
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart
Conclusion
Windows containers on Windows Server 2022 provide a practical path to containerising Windows-native workloads. By choosing the appropriate base image — Server Core for broad compatibility, Nano Server for modern .NET microservices, or the IIS image for web hosting — you can build minimal and efficient containers tailored to your application. Combined with flexible networking modes and the choice between process and Hyper-V isolation, Windows containers on Server 2022 deliver production-grade container infrastructure for Windows environments.