Introduction to Windows Server 2019 Containers

Windows Server 2019 includes native support for containerization, enabling organizations to run applications in isolated, lightweight environments called containers. Unlike virtual machines, containers share the host OS kernel but maintain isolation through namespaces and resource controls. Windows Server 2019 supports two container isolation types: process isolation and Hyper-V isolation. Process isolation uses Windows kernel namespaces for lightweight isolation where all containers share the host kernel. Hyper-V isolation runs each container in a lightweight utility VM providing stronger isolation suitable for multi-tenant environments or running untrusted code. Windows Server 2019 also supports Linux containers in Hyper-V isolation mode through the Linux Containers on Windows (LCOW) feature.

Prerequisites for Windows Containers

Windows Server 2019 must be running with at least 4 GB of RAM and adequate disk space for container images, which can be 5-10 GB each. The server must have internet access to pull container images from Docker Hub or Microsoft Container Registry, or an internal registry must be available. Hyper-V isolation requires the Hyper-V role installed and the CPU must support hardware virtualization. Verify hardware virtualization support:

Get-ComputerInfo -Property HyperV*
systeminfo | findstr /i "hyper-v"

Installing the Containers Feature

Enable the Containers feature on Windows Server 2019. This feature is required for running both process-isolated and Hyper-V-isolated Windows containers:

Install-WindowsFeature Containers -Restart

If Hyper-V isolation is needed, also install the Hyper-V role:

Install-WindowsFeature Hyper-V -IncludeManagementTools -Restart

Verify the Containers feature is installed:

Get-WindowsFeature Containers, Hyper-V | Select-Object Name, InstallState

Installing Docker on Windows Server 2019

Docker is the container runtime for Windows Server 2019. Install the Docker Engine using PowerShell from the PowerShell Gallery:

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name docker -ProviderName DockerMsftProvider -Force -RequiredVersion 20.10.9
Restart-Computer -Force

After restart, verify Docker installation and service status:

docker version
docker info
Get-Service docker | Select-Object Status, DisplayName

Pulling Windows Container Base Images

Microsoft provides several Windows container base images from the Microsoft Container Registry (mcr.microsoft.com). The primary base images for Windows Server 2019 containers are Windows Server Core (a large image with most Win32 APIs), Nano Server (a minimal image with limited APIs, optimized for .NET Core), and the Windows image (the full Windows base). Pull the Windows Server Core image matching your host OS version:

docker pull mcr.microsoft.com/windows/servercore:ltsc2019
docker pull mcr.microsoft.com/windows/nanoserver:1809
docker pull mcr.microsoft.com/windows:1809

List downloaded images:

docker images

The first pull takes time as the images are several gigabytes. Subsequent pulls of images based on the same layers are fast.

Running Your First Windows Container

Run a basic Windows container to verify the environment is working correctly. Run an interactive PowerShell session in a Server Core container:

docker run -it mcr.microsoft.com/windows/servercore:ltsc2019 powershell

Inside the container, run commands to verify the isolated environment:

hostname
ipconfig
Get-Process
exit

Run a detached container and inspect it:

docker run -d --name web01 -p 80:80 mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
docker ps
docker inspect web01
docker logs web01

Creating a Custom Windows Container Image

Build custom container images using a Dockerfile. Create a directory for the build context and write a Dockerfile to containerize a sample ASP.NET application:

mkdir C:DockerBuildWebApp
cd C:DockerBuildWebApp

Create the Dockerfile with the following content:

FROM mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN Remove-Item -Recurse C:inetpubwwwroot*
COPY index.html C:inetpubwwwroot
EXPOSE 80
CMD ["ping", "-t", "localhost"]

Create a sample index.html and build the image:

echo "

Hello from Windows Container

" > C:DockerBuildWebAppindex.html docker build -t contoso/webapp:1.0 C:DockerBuildWebApp docker run -d --name webapp -p 8080:80 contoso/webapp:1.0

Configuring Container Networking

Windows containers support several network modes. NAT is the default, where containers get private IP addresses and the host performs NAT for outbound traffic. Transparent mode connects containers directly to the physical network. Overlay networking connects containers across multiple hosts using a virtual network. Configure a custom NAT network:

docker network create -d nat --subnet=172.20.0.0/16 --gateway=172.20.0.1 CorpNAT
docker run -d --network CorpNAT --name db01 mcr.microsoft.com/windows/servercore:ltsc2019

For transparent networking where containers get IP addresses directly from your network:

docker network create -d transparent --subnet=192.168.1.0/24 --gateway=192.168.1.1 CorpTransparent

Inspect network configuration:

docker network ls
docker network inspect CorpNAT

Configuring Container Storage

Containers have ephemeral storage by default, meaning data written inside a container is lost when the container is removed. Use volumes or bind mounts to persist data. Create a Docker volume and mount it into a container:

docker volume create AppData
docker run -d --name sqlcontainer -v AppData:C:SQLData -e sa_password=P@ssw0rd! -e ACCEPT_EULA=Y mcr.microsoft.com/mssql/server:2019-latest

Use a bind mount to map a host directory into a container:

docker run -d --name webserver -v C:WebContent:C:inetpubwwwroot -p 80:80 mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019

Using Hyper-V Isolation

Run containers with Hyper-V isolation for stronger security boundaries. This is required when the container image OS version does not match the host OS version, or for running multiple container OS versions on the same host:

docker run -it --isolation=hyperv mcr.microsoft.com/windows/servercore:ltsc2019 powershell
docker run -d --isolation=hyperv --name hyperv-web -p 8081:80 mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019

Verify isolation type of running containers:

docker inspect hyperv-web --format "{{.HostConfig.Isolation}}"

Managing Container Resources

Control CPU and memory resources allocated to containers to prevent resource contention. Limit a container to 2 CPU cores and 2 GB of RAM:

docker run -d --name limited-app --cpus="2.0" --memory="2g" --memory-swap="4g" mcr.microsoft.com/windows/servercore:ltsc2019

Monitor resource usage of running containers:

docker stats
docker stats --no-stream --format "table {{.Name}}t{{.CPUPerc}}t{{.MemUsage}}"

Setting Up a Private Container Registry

Run a private Docker registry on your network to host custom images without relying on Docker Hub. Deploy the registry container:

docker run -d -p 5000:5000 --restart always --name registry -v C:RegistryData:/var/lib/registry registry:2

Tag and push a local image to the private registry:

docker tag contoso/webapp:1.0 localhost:5000/contoso/webapp:1.0
docker push localhost:5000/contoso/webapp:1.0
docker pull localhost:5000/contoso/webapp:1.0

Windows Server 2019 containers provide a powerful way to deploy and manage applications with consistent environments, reduced conflicts, and faster startup times compared to traditional virtual machines.