Disclaimer: this handles problems due to incorrect file permissions, not because a process may hold a handle to non deletable files.

Recently I came up with a - problably - bug in Docker Desktop which left a huge folder windowsfilter inside the docker data folder.
It looked like the working space of a docker image containing all the system stuff that is required for execution of a Windows image.
Unfortunately it couldn’t be removed easily, and all subfolders belong to another user, which required an elevation for each item - what no one would really like to do, especially when it takes over 12hrs to remove the 800gb of waste data.

However, fortunately there is a solution (which requires admin rights, by the way).

If you try to remove the docker windowsfilter folder, do those steps first:

  1. Stop all possibly running containers:
    docker container stop ...
  2. Remove all containers:
    docker container rm ...
  3. Remove all images:
    docker image rm ...
  4. Prune everything (normally this includes step 2 + 3):
    docker system prune -af
  5. Stop Docker Desktop

Now the folder removement can start.

  1. Take ownership of the folder (and all subsequent items)
    takeown /R /F folder
  2. Allow deletion of folder by granting full access (F) (recursivly /t) to user, errors will be ignored by using /c
    icacls folder /t /c /grant user:F > nul
    icacls folder /t /reset > nul
  3. Remove the folder
    rd /S /Q folder > nul

Step 3 may not fully work yet, if so, you can try this by running a small python script I wrote for this purpose, for example named cleanup.py:

import sys
import os
from itertools import chain
from pathlib import Path

def delete_path(path):
    try:
        path.rmdir() if path.is_dir() else path.unlink()
    except (OSError, PermissionError) as exc:
        print(exc)

def clean(rootpath, user):
    for root, dirs, files in os.walk(rootpath, topdown=True, followlinks=False):
        for pathname in chain(files, dirs):
            path = Path(root, pathname)
            try:
                os.system(f'icacls "{path}" /grant:r {user}:F')
            except (OSError, PermissionError) as exc:
                print(exc)
            else:
                delete_path(path)                

clean(*sys.argv[1:2])

Simply call it from an admin command line and pass the folder as first, user as second argument:
py -3.12 cleanup.py E:\docker-data\windowsfilter Administrator

Depending on how much files are contained in this folder, this will take up to hours to finish.
After that, some or all folders inside may still exists, but now you should be able to delete them directly from the explorer. In may case Windows asked a few times if deletion of a protected file should proceed, which I marked as for all and confirmed.
But now it worked, and some time later I got rid of that data waste.

If you want to clean up orphaned data in your docker env, you could also have a look at docker-ci-zap.