How to Configure Windows Server 2016 Container Networking

Container networking on Windows Server 2016 is managed through the Host Networking Service (HNS) and exposed to Docker through network drivers. Windows supports several networking modes, each suited to different deployment scenarios: NAT for isolated single-host networking, Transparent for direct connectivity to the physical network, L2Bridge and L2Tunnel for SDN and Azure environments, and Overlay for multi-host container clusters. Understanding these modes and how to configure them correctly is essential for building reliable containerized applications on Windows. This tutorial covers each network type, how to create and inspect networks, how to control DNS and port mappings, and how to troubleshoot common networking problems.

Prerequisites

A Windows Server 2016 host with Docker installed and running is required. You should be familiar with basic Docker commands from the previous tutorial. An elevated PowerShell session is used throughout. For multi-host overlay networking, you additionally need Docker Swarm or another orchestrator configured, and all hosts must be able to communicate on UDP port 4789 (VXLAN).

Step 1: Understand Windows Container Network Drivers

Windows container networking uses the following drivers. NAT creates an internal virtual switch and performs network address translation so containers share the host IP for outbound connections. Transparent bridges the container directly to the physical network so it receives its own IP from the external DHCP server or through static assignment. L2Bridge is similar to transparent but allows the container and host to share the same IP subnet and MAC address prefix. Overlay creates a distributed virtual network across multiple Docker hosts using VXLAN encapsulation, required for Docker Swarm services.

Step 2: Inspect Default Docker Networks

After Docker is installed, a default NAT network named nat is created automatically. List existing networks to see what is available.

docker network ls
docker network inspect nat

The inspect output shows the subnet, gateway, and any containers currently connected to the network. The default NAT network uses the 172.16.0.0/12 range unless customized in daemon.json.

Step 3: Create a Custom NAT Network

Creating a custom NAT network lets you control the subnet, gateway, and IP range assigned to containers. This is useful when you need predictable IP addressing or when you need to avoid conflicts with existing network ranges.

docker network create --driver nat `
    --subnet 10.10.10.0/24 `
    --gateway 10.10.10.1 `
    --opt com.docker.network.windowsshim.vlanid=100 `
    mynat

Run a container on the new network and verify it receives an address in the expected range.

docker run -d --name test1 --network mynat `
    mcr.microsoft.com/windows/servercore:ltsc2016 ping -t localhost

docker inspect test1 --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'

Step 4: Configure Port Publishing

Port publishing maps a host port to a container port, allowing external traffic to reach services running inside containers. Use the -p flag with docker run.

# Map host port 8080 to container port 80
docker run -d --name webserver -p 8080:80 `
    mcr.microsoft.com/windows/servercore:ltsc2016

# Map multiple ports
docker run -d --name multiport -p 8080:80 -p 4443:443 `
    mcr.microsoft.com/windows/servercore:ltsc2016

# Verify port mappings
docker port webserver

Add a Windows Firewall rule to allow inbound traffic on the published port.

New-NetFirewallRule -DisplayName 'Container Web 8080' -Direction Inbound `
    -Protocol TCP -LocalPort 8080 -Action Allow

Step 5: Create a Transparent Network

A transparent network gives each container a direct presence on the physical network. The container gets its own IP address from your DHCP server or from a static pool you define. This requires your physical or virtual switch to allow MAC address spoofing if running in a VM.

docker network create --driver transparent `
    --subnet 192.168.1.0/24 `
    --gateway 192.168.1.1 `
    --ip-range 192.168.1.200/29 `
    mytransparent

If running in Hyper-V, enable MAC address spoofing on the VM’s network adapter first.

Set-VMNetworkAdapter -VMName 'ContainerHost' -MacAddressSpoofing On

Step 6: Connect Containers to Multiple Networks

A container can be connected to more than one network simultaneously. This is useful for frontend-backend separation where a web container needs access to both a public-facing network and a private backend network.

# Create two networks
docker network create --driver nat --subnet 10.11.0.0/24 frontend
docker network create --driver nat --subnet 10.12.0.0/24 backend

# Start a container on the frontend network
docker run -d --name webapp --network frontend `
    mcr.microsoft.com/windows/servercore:ltsc2016 ping -t localhost

# Connect the same container to the backend network
docker network connect backend webapp

# Verify both network connections
docker inspect webapp --format '{{json .NetworkSettings.Networks}}' | ConvertFrom-Json

Step 7: Configure Container DNS

By default, containers inherit the DNS configuration of the Docker daemon. You can override DNS settings per container or set defaults in daemon.json.

# Override DNS for a single container
docker run -d --name dnstest --dns 192.168.1.10 --dns-search corp.local `
    mcr.microsoft.com/windows/servercore:ltsc2016 ping -t localhost

# Set default DNS in daemon.json (applies to all new containers)
$daemonConfig = @{
    "dns" = @("192.168.1.10", "192.168.1.11")
    "dns-search" = @("corp.local")
} | ConvertTo-Json

$daemonConfig | Set-Content 'C:ProgramDataDockerconfigdaemon.json'
Restart-Service Docker

Step 8: Use the Host Networking Service for Diagnostics

The Host Networking Service (HNS) is the Windows component that underpins all container networking. You can query it directly via PowerShell for advanced diagnostics.

# List all HNS networks
Get-HnsNetwork | Select-Object Name, Type, Subnets

# List all HNS endpoints
Get-HnsEndpoint | Select-Object Name, IPAddress, MacAddress, IsRemoteEndpoint

# Inspect a specific network
Get-HnsNetwork | Where-Object Name -eq 'mynat' | ConvertTo-Json -Depth 5

Step 9: Troubleshoot Container Connectivity

If containers cannot communicate with each other or with external hosts, use the following diagnostic steps to identify the problem.

# Test connectivity from inside a container
docker exec mycontainer ping -n 4 8.8.8.8
docker exec mycontainer ipconfig /all
docker exec mycontainer netstat -an

# Check the WinNAT module is loaded
Get-NetNat
Get-NetNatStaticMapping

# Restart Docker networking stack if needed
Stop-Service Docker
Stop-Service hns
Start-Service hns
Start-Service Docker

Step 10: Configure Overlay Networking for Docker Swarm

Overlay networks allow containers on different hosts in a Docker Swarm to communicate as if on the same virtual network. Initialize a Swarm and create an overlay network as follows.

# Initialize Docker Swarm on the manager node
docker swarm init --advertise-addr 192.168.1.100

# Create an overlay network
docker network create --driver overlay --attachable myoverlay

# Deploy a service on the overlay network
docker service create --name webfarm --replicas 3 `
    --network myoverlay -p 80:80 `
    mcr.microsoft.com/windows/servercore:ltsc2016

Configuring container networking correctly on Windows Server 2016 is critical for ensuring that containerized applications are accessible, isolated, and performant. This guide has covered the main network drivers, port publishing, DNS configuration, multi-network container connectivity, HNS diagnostics, and overlay networking for Swarm deployments. As you build more complex environments, document your network topology carefully and use consistent naming conventions for Docker networks to simplify troubleshooting. Always validate firewall rules on both the host and any intervening network devices when containers fail to communicate with external services.