Knowledge Base

Find answers to common questions about Cloudmersive products and services.



How to Completely Reset Docker on Windows and Recover Disk Space from windowsfilter
9/26/2026 - Cloudmersive Support


Docker on Windows can occasionally leave behind large amounts of container layer data under the Docker data directory, particularly in:

C:\ProgramData\Docker\windowsfilter

In some cases, normal Docker cleanup commands such as:

docker system prune -a
docker builder prune -a
docker image prune -a

may not recover all disk space consumed by Windows container layers.

This article provides a complete Docker local state reset script for Windows that stops the relevant Windows services, attempts to destroy Windows container layers through the Windows Host Compute Service storage API, removes the Docker data directory, recreates it, and starts the services again.

WARNING: THIS IS A DESTRUCTIVE FULL RESET OF LOCAL DOCKER STATE.

This script is intended only for experienced Windows administrators who have reviewed the script and fully understand the consequences of completely resetting Docker's local state.

Running this script can permanently and irrecoverably delete:

  • All local Docker containers
  • All local Docker images
  • All Docker build cache
  • All Docker volumes stored within the Docker data root
  • All local container layers
  • Docker network state stored within the Docker data root
  • Other Docker state stored under the configured Docker data directory

There is no undo operation.

Do not run this script on a system containing Docker state that must be preserved.

This procedure is generally most appropriate for disposable development, CI/CD, build, or container-builder systems where local Docker state can safely be recreated.

When This May Be Useful

This procedure may be useful when a Windows Docker host has accumulated a large amount of disk usage that is not being reclaimed through normal Docker cleanup operations.

For example, the following directory may consume tens or hundreds of gigabytes:

C:\ProgramData\Docker\windowsfilter

while Docker itself reports considerably less reclaimable disk space.

Windows container layers are not ordinary directories. They are managed through the Windows container storage subsystem and Host Compute Service APIs. As a result, attempting to manually delete individual windowsfilter directories can result in access-denied errors, incomplete cleanup, or damaged Docker state.

The script below performs a complete local Docker state reset rather than attempting to selectively repair individual Docker layers.

Requirements

Run this procedure only if all of the following are true:

  • You are a Windows administrator.
  • You are running the script directly on the Windows Docker host.
  • You understand that all local Docker state will be permanently deleted.
  • You have reviewed the script before execution.
  • Any important data stored in Docker volumes or containers has already been backed up.
  • You have confirmed that Docker can safely be rebuilt from source images, registries, Dockerfiles, or other external sources.
  • You agree to the Cloudmersive Terms of Service.

The script must be run from an elevated PowerShell session.

Save the Reset Script

Save the following script as:

Reset-DockerWindowsState.ps1

Review the entire script before executing it.

# Copyright Cloudmersive LLC 2026
#
# Reset-DockerWindowsState.ps1
#
# COMPLETE AND IRREVERSIBLE DOCKER STATE RESET FOR WINDOWS.
#
# IMPORTANT:
# USE OF THIS SCRIPT REQUIRES THAT YOU READ AND AGREE TO THE
# CLOUDMERSIVE TERMS OF SERVICE:
#
# https://portal.cloudmersive.com/terms-of-service
#
# IF YOU DO NOT AGREE TO THE CLOUDMERSIVE TERMS OF SERVICE,
# YOU MAY NOT USE THIS SCRIPT.
#
# This script permanently deletes local Docker state, including containers,
# images, layers, build cache, volumes stored in the Docker data root, and
# other Docker state.
#
# USE ONLY IF YOU ARE AN EXPERIENCED WINDOWS ADMINISTRATOR AND HAVE FULLY
# REVIEWED AND UNDERSTOOD THE CONSEQUENCES OF RUNNING THIS SCRIPT.
#
# THIS OPERATION CAN CAUSE IRREVERSIBLE DATA LOSS.

$ErrorActionPreference = "Continue"

$TermsUrl = "https://portal.cloudmersive.com/terms-of-service"

Write-Host ""
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host " Cloudmersive - Docker for Windows Full State Reset" -ForegroundColor Yellow
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host ""
Write-Host "Copyright Cloudmersive LLC 2026"
Write-Host ""
Write-Host "WARNING: THIS SCRIPT PERMANENTLY DELETES ALL LOCAL DOCKER STATE." -ForegroundColor Red
Write-Host ""
Write-Host "This includes, but is not limited to:"
Write-Host "  - Containers"
Write-Host "  - Images"
Write-Host "  - Windows container layers"
Write-Host "  - Build cache"
Write-Host "  - Docker volumes stored inside the Docker data root"
Write-Host "  - Docker network state"
Write-Host "  - Other data stored inside the Docker data root"
Write-Host ""
Write-Host "THIS OPERATION CANNOT BE UNDONE." -ForegroundColor Red
Write-Host ""
Write-Host "Use of this script requires that you read and agree to the"
Write-Host "Cloudmersive Terms of Service:" -ForegroundColor Yellow
Write-Host $TermsUrl -ForegroundColor Cyan
Write-Host ""
Write-Host "If you do not agree to the Terms of Service, do not use this script." -ForegroundColor Yellow
Write-Host ""

# ----------
# Verify Administrator
# ----------

$CurrentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object Security.Principal.WindowsPrincipal($CurrentIdentity)

if (-not $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
    Write-Host ""
    Write-Host "ERROR: This script must be run from an elevated PowerShell session." -ForegroundColor Red
    Write-Host "Right-click PowerShell and select 'Run as administrator'." -ForegroundColor Red
    exit 1
}

# ----------
# Terms of Service acceptance
# ----------

Write-Host "By continuing, you confirm that you have read and agree to:" -ForegroundColor Yellow
Write-Host $TermsUrl -ForegroundColor Cyan
Write-Host ""

$TermsAcceptance = Read-Host "Type I AGREE to accept the Cloudmersive Terms of Service and continue"

if ($TermsAcceptance -cne "I AGREE")
{
    Write-Host ""
    Write-Host "Terms of Service were not accepted. No changes were made." -ForegroundColor Yellow
    exit 1
}

# ----------
# Final destructive-operation confirmation
# ----------

Write-Host ""
Write-Host "FINAL WARNING" -ForegroundColor Red
Write-Host ""
Write-Host "You are about to permanently erase the local Docker state on this machine."
Write-Host "This operation may result in irreversible data loss."
Write-Host ""

$ResetConfirmation = Read-Host "Type DELETE ALL DOCKER STATE to continue"

if ($ResetConfirmation -cne "DELETE ALL DOCKER STATE")
{
    Write-Host ""
    Write-Host "Confirmation failed. No changes were made." -ForegroundColor Yellow
    exit 1
}

# ----------
# Determine Docker data root
# ----------

$DockerRoot = $null

try
{
    $DetectedDockerRoot = docker info --format '{{.DockerRootDir}}' 2>$null

    if ($LASTEXITCODE -eq 0 -and $DetectedDockerRoot)
    {
        $DockerRoot = $DetectedDockerRoot.Trim()
    }
}
catch
{
}

if (-not $DockerRoot)
{
    $DockerRoot = "C:\ProgramData\Docker"
    Write-Host ""
    Write-Warning "Docker data root could not be detected automatically."
    Write-Warning "Using default Windows Docker data root: $DockerRoot"
}

$DockerRoot = $DockerRoot.TrimEnd('\')

# Safety validation to avoid catastrophic deletion caused by an invalid path.

$ForbiddenRoots = @(
    "C:",
    "C:\",
    "D:",
    "D:\",
    "E:",
    "E:\",
    "\"
)

if ($ForbiddenRoots -contains $DockerRoot)
{
    Write-Host ""
    Write-Host "ERROR: Refusing to operate on unsafe Docker root: $DockerRoot" -ForegroundColor Red
    exit 1
}

$WindowsFilter = Join-Path $DockerRoot "windowsfilter"

Write-Host ""
Write-Host "Docker data root that will be permanently deleted:" -ForegroundColor Yellow
Write-Host "  $DockerRoot" -ForegroundColor Yellow
Write-Host ""

$PathConfirmation = Read-Host "Type RESET to confirm this Docker data root"

if ($PathConfirmation -cne "RESET")
{
    Write-Host ""
    Write-Host "Docker data-root confirmation failed. No changes were made." -ForegroundColor Yellow
    exit 1
}

# ----------
# Record free disk space before reset
# ----------

$DriveLetter = [System.IO.Path]::GetPathRoot($DockerRoot).TrimEnd('\')

$FreeBefore = $null

try
{
    $FreeBefore = (Get-PSDrive -Name $DriveLetter.TrimEnd(':')).Free
}
catch
{
}

# ----------
# Stop Docker and Windows container compute services
# ----------

Write-Host ""
Write-Host "Stopping Docker services..." -ForegroundColor Cyan

Stop-Service docker -Force -ErrorAction SilentlyContinue

Write-Host "Stopping Windows Host Compute Service..." -ForegroundColor Cyan

Stop-Service vmcompute -Force -ErrorAction SilentlyContinue

Start-Sleep -Seconds 3

# ----------
# Load Windows Compute Storage API
# ----------

Write-Host ""
Write-Host "Loading Windows container storage API..." -ForegroundColor Cyan

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public static class CloudmersiveHcsNative
{
    [DllImport("ComputeStorage.dll",
        CharSet = CharSet.Unicode,
        SetLastError = true)]
    public static extern int HcsDestroyLayer(string layerPath);
}
"@ -ErrorAction SilentlyContinue

# ----------
# Destroy Windows container layers through HCS
# ----------

if (Test-Path $WindowsFilter)
{
    Write-Host ""
    Write-Host "Enumerating Windows container layers..." -ForegroundColor Cyan

    $Layers = @(Get-ChildItem $WindowsFilter -Directory -Force -ErrorAction SilentlyContinue)

    Write-Host "Found $($Layers.Count) layer directories."
    Write-Host ""

    foreach ($Layer in $Layers)
    {
        Write-Host "Destroying layer: $($Layer.Name)"

        try
        {
            $Result = [CloudmersiveHcsNative]::HcsDestroyLayer($Layer.FullName)

            if ($Result -eq 0)
            {
                Write-Host "  HCS destroy completed." -ForegroundColor Green
            }
            else
            {
                Write-Warning ("  HcsDestroyLayer returned HRESULT 0x{0:X8}" -f ($Result -band 0xffffffff))
            }
        }
        catch
        {
            Write-Warning "  HCS layer destruction failed: $($_.Exception.Message)"
        }
    }
}
else
{
    Write-Host ""
    Write-Host "No windowsfilter directory found at:" -ForegroundColor Yellow
    Write-Host "  $WindowsFilter"
}

# ----------
# Delete the remaining Docker state
# ----------

Write-Host ""
Write-Host "Deleting remaining Docker state..." -ForegroundColor Cyan
Write-Host "This step can take a considerable amount of time on systems containing"
Write-Host "large Windows container layer stores."
Write-Host ""

if (Test-Path $DockerRoot)
{
    cmd.exe /c "rd /s /q `"$DockerRoot`""
}

# ----------
# Verify removal
# ----------

if (Test-Path $DockerRoot)
{
    Write-Host ""
    Write-Warning "Some Docker data remains under:"
    Write-Warning $DockerRoot
    Write-Warning ""
    Write-Warning "The system may require further investigation or a reboot before"
    Write-Warning "remaining Windows container storage objects can be removed."
}
else
{
    Write-Host ""
    Write-Host "Docker data root successfully removed." -ForegroundColor Green
}

# ----------
# Recreate Docker data directory
# ----------

if (-not (Test-Path $DockerRoot))
{
    Write-Host ""
    Write-Host "Creating clean Docker data root..." -ForegroundColor Cyan

    New-Item -ItemType Directory -Path $DockerRoot -Force | Out-Null
}

# ----------
# Restart Windows container services
# ----------

Write-Host ""
Write-Host "Starting Windows Host Compute Service..." -ForegroundColor Cyan

Start-Service vmcompute -ErrorAction SilentlyContinue

Write-Host "Starting Docker..." -ForegroundColor Cyan

Start-Service docker -ErrorAction SilentlyContinue

Start-Sleep -Seconds 3

# ----------
# Report service state
# ----------

Write-Host ""
Write-Host "Service status:" -ForegroundColor Cyan

Get-Service docker, vmcompute -ErrorAction SilentlyContinue |
    Select-Object Name, Status |
    Format-Table -AutoSize

# ----------
# Report new Docker data-root size
# ----------

Write-Host ""
Write-Host "Current Docker data-root size:" -ForegroundColor Cyan

try
{
    $RemainingBytes = (
        Get-ChildItem $DockerRoot -Recurse -Force -File -ErrorAction SilentlyContinue |
        Measure-Object Length -Sum
    ).Sum

    if (-not $RemainingBytes)
    {
        $RemainingBytes = 0
    }

    Write-Host ("{0:N2} GB" -f ($RemainingBytes / 1GB))
}
catch
{
    Write-Warning "Unable to calculate Docker data-root size."
}

# ----------
# Report approximate disk space recovered
# ----------

if ($null -ne $FreeBefore)
{
    try
    {
        $FreeAfter = (Get-PSDrive -Name $DriveLetter.TrimEnd(':')).Free
        $Recovered = $FreeAfter - $FreeBefore

        Write-Host ""
        Write-Host "Approximate disk space recovered:" -ForegroundColor Cyan
        Write-Host ("{0:N2} GB" -f ($Recovered / 1GB))
    }
    catch
    {
    }
}

Write-Host ""
Write-Host "============================================================" -ForegroundColor Green
Write-Host " Docker state reset completed." -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host ""
Write-Host "All previous local Docker state should be considered permanently deleted."
Write-Host "Required images must be pulled or rebuilt again."
Write-Host ""

Run the Script

Open PowerShell as Administrator, change to the directory containing the script, and run:

Set-ExecutionPolicy -Scope Process Bypass
.\Reset-DockerWindowsState.ps1

The script requires several explicit confirmations before performing any destructive operation.

First, the administrator must read and agree to the Cloudmersive Terms of Service:

https://portal.cloudmersive.com/terms-of-service

The administrator must then separately acknowledge that all Docker state will be deleted and confirm the Docker data directory that will be reset.

What the Script Does

The script performs the following operations:

  1. Verifies that PowerShell is running with Administrator privileges.
  2. Requires explicit acceptance of the Cloudmersive Terms of Service.
  3. Requires explicit confirmation of the irreversible Docker state reset.
  4. Attempts to determine the current Docker data root.
  5. Stops the Docker service.
  6. Stops the Windows Host Compute Service (vmcompute).
  7. Enumerates Windows container layers under windowsfilter.
  8. Calls the Windows HcsDestroyLayer API for each layer.
  9. Deletes the remaining Docker data root.
  10. Creates a new empty Docker data directory.
  11. Restarts the Windows Host Compute Service.
  12. Restarts Docker.
  13. Reports the resulting service status and approximate disk space recovered.

Why windowsfilter Can Be Difficult to Delete

Windows container storage differs substantially from ordinary filesystem directories.

Windows container layers are managed through the Windows container storage and Host Compute Service infrastructure. Layer directories may contain state associated with container filesystem filters, reparse points, copy-on-write behavior, and Windows container layer metadata.

As a result, attempting to recover disk space by manually deleting directories such as:

C:\ProgramData\Docker\windowsfilter\<layer>

may fail with errors such as:

Access is denied.

It can also leave Docker or the Windows container storage subsystem in an inconsistent state.

This script therefore attempts to destroy each Windows container layer through the Windows HcsDestroyLayer API before deleting the remaining Docker data directory.

This Is a State Reset, Not Routine Maintenance

This procedure should not be used as routine Docker maintenance.

For ordinary Docker cleanup, administrators should first use the normal Docker lifecycle and cleanup mechanisms appropriate for their environment.

This full-reset procedure is intended for situations where:

  • Docker local state can safely be discarded.
  • Normal Docker cleanup has already proven insufficient.
  • A Windows container build or development system has accumulated substantial unwanted disk usage.
  • The administrator is prepared to recreate all required local Docker state.

Production systems containing persistent Docker volumes, unique local images, or irreplaceable container data should not be reset using this procedure unless appropriate backups and recovery procedures have been validated.

Final Warning

Running Reset-DockerWindowsState.ps1 deletes and recreates Docker's local data store.

All Docker state within the selected Docker data root should be considered permanently and irrecoverably deleted.

Only experienced administrators who have reviewed the source code and fully understand the impact of a complete Docker state reset should execute the script.

Use of the script requires agreement to the Cloudmersive Terms of Service:

https://portal.cloudmersive.com/terms-of-service

600 free API calls/month, with no expiration

Sign Up Now or Sign in with Google    Sign in with Microsoft

Questions? We'll be your guide.

Contact Sales