How to Set Up Windows Server 2019 Container Monitoring
Monitoring Windows containers running on Windows Server 2019 is essential for ensuring application health, detecting performance bottlenecks, and responding quickly to failures. Unlike Linux container monitoring, Windows container monitoring has some platform-specific considerations and tool differences. This guide covers setting up comprehensive container monitoring using Windows-native tools, Prometheus with Windows exporters, and integration with Azure Monitor for centralized observability.
Native Container Monitoring with Docker Stats
Docker provides built-in monitoring through the docker stats command, which streams real-time CPU, memory, network, and disk I/O metrics for all running containers. View current stats for all containers:
docker stats --no-stream --format "table {{.Name}}t{{.CPUPerc}}t{{.MemUsage}}t{{.MemPerc}}t{{.NetIO}}t{{.BlockIO}}"
Monitor a specific container continuously:
docker stats my_webapp --format "{{.Name}}: CPU={{.CPUPerc}} MEM={{.MemUsage}} NET={{.NetIO}}"
Retrieve container resource statistics using the Docker API via PowerShell for scripted monitoring:
$containerId = docker ps -q --filter name=my_webapp
$stats = Invoke-RestMethod -Uri "http://localhost:2375/containers/$containerId/stats?stream=false"
$stats | ConvertTo-Json -Depth 5
Monitoring with Windows Performance Counters
Windows Server 2019 exposes container metrics through the standard Windows Performance Counter infrastructure. Container-specific counters appear under Hyper-V Dynamic Memory VM and Hyper-V Worker Virtual Processor when using Hyper-V isolation. View available container-related performance counters:
Get-Counter -ListSet "Hyper-V*" | Select CounterSetName, Description
Get-Counter -ListSet "Container*" | Select CounterSetName, Description
Collect specific performance counter data for containers:
Get-Counter `
-Counter "Hyper-V Dynamic Memory VM(*)Physical Memory" `
-SampleInterval 5 `
-MaxSamples 10 |
Select-Object -ExpandProperty CounterSamples |
Format-Table InstanceName, CookedValue
Deploying Windows Container Exporter for Prometheus
The windows_exporter is the standard Prometheus exporter for Windows metrics and includes container-specific collectors. Deploy it on each container host to expose metrics for scraping by Prometheus:
$exporterVersion = "0.24.0"
Invoke-WebRequest `
-Uri "https://github.com/prometheus-community/windows_exporter/releases/download/v$exporterVersion/windows_exporter-$exporterVersion-amd64.exe" `
-OutFile "C:Monitoringwindows_exporter.exe" `
-UseBasicParsing
New-Item -ItemType Directory -Path "C:Monitoring" -Force
Install windows_exporter as a service with container-related collectors enabled:
sc.exe create "windows_exporter" `
binPath= "C:Monitoringwindows_exporter.exe --collectors.enabled=os,cpu,memory,logical_disk,net,container,process --telemetry.addr=:9182" `
start= auto `
DisplayName= "Windows Metrics Exporter"
sc.exe start windows_exporter
Allow the exporter port through the firewall:
New-NetFirewallRule `
-DisplayName "Windows Exporter 9182" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 9182 `
-Action Allow
Configuring Prometheus to Scrape Windows Container Hosts
Add the Windows container hosts to the Prometheus configuration. Edit prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'windows-container-hosts'
static_configs:
- targets:
- '10.0.0.10:9182'
- '10.0.0.11:9182'
- '10.0.0.12:9182'
relabel_configs:
- source_labels: [__address__]
target_label: host
regex: '([^:]+):.*'
replacement: '$1'
- job_name: 'docker-daemon'
static_configs:
- targets:
- '10.0.0.10:9323'
Enabling Docker Metrics Endpoint
Configure Docker to expose a Prometheus metrics endpoint on port 9323. Update the Docker daemon configuration:
$config = Get-Content "C:ProgramDatadockerconfigdaemon.json" | ConvertFrom-Json
$config | Add-Member -Type NoteProperty -Name "metrics-addr" -Value "0.0.0.0:9323" -Force
$config | Add-Member -Type NoteProperty -Name "experimental" -Value $true -Force
$config | ConvertTo-Json | Set-Content "C:ProgramDatadockerconfigdaemon.json"
Restart-Service docker
Container Log Monitoring
Collect and centralize container logs for analysis. Configure Docker to use the json-file logging driver with size limits and rotation:
@"
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5",
"labels": "environment,app",
"env": "HOSTNAME"
}
}
"@ | Set-Content "C:ProgramDatadockerconfigdaemon.json"
For centralized logging, use the Fluent Bit log forwarder to ship container logs to Elasticsearch or Azure Log Analytics:
docker run -d `
--name fluent-bit `
--restart always `
-v "C:ProgramDatadockercontainers:C:varlibdockercontainers:ro" `
-e FLUENT_ELASTICSEARCH_HOST=elasticsearch.contoso.local `
-e FLUENT_ELASTICSEARCH_PORT=9200 `
cr.fluentbit.io/fluent/fluent-bit:latest `
-c /etc/fluent-bit/fluent-bit.conf
Azure Monitor Container Insights
For AKS clusters with Windows Server 2019 nodes, Azure Monitor Container Insights provides comprehensive monitoring. Enable it when creating or updating the cluster:
az monitor log-analytics workspace create `
--resource-group rg-monitoring `
--workspace-name law-containers
$workspaceId = az monitor log-analytics workspace show `
--resource-group rg-monitoring `
--workspace-name law-containers `
--query id -o tsv
az aks enable-addons `
--resource-group rg-aks-windows `
--name aks-ws2019-cluster `
--addons monitoring `
--workspace-resource-id $workspaceId
Query container performance data using KQL in Log Analytics:
Perf
| where ObjectName == "K8SContainer"
| where CounterName == "cpuUsageNanoCores"
| summarize avg(CounterValue) by bin(TimeGenerated, 5m), InstanceName
| render timechart
Container monitoring on Windows Server 2019 requires combining Docker’s native stats, Windows Performance Counters, Prometheus exporters, and log aggregation for complete visibility. Investing in monitoring infrastructure before production deployment ensures you have the data needed to diagnose issues quickly and optimize resource utilization across your container workloads.