There are cases of bind-mounts on Docker for Windows, where inode-related changes are not propagated. To be more precise, it seems to be related to similar paths having a common denominator which exists as a directory itself and which are junctioned on the NTFS filesystem inside or outside the project root.
Windows 10 Pro, Docker for Windows (at least V4, several versions). Latest confirmed version: 4.1.* up to 4.3.1 (72247) Docker Engine: 20.10.11
Not tested using WSL Backend!
Tested on a system using 2.1.0.5 which works flawlessly, but is missing inotify events. Changes do propagate correctly with that version.
If you cloned the repo successfully, open up a PowerShell or Windows Terminal using a PS and go to the repo directory.
cd adummy-test- Create the needed NTFS junctions by executing
.\create_junctions.bat - Run the environment via
docker-compose up - Go through each folder in adummy-targetdirs and do something (edit a file, create one, etc.)
- If finished or testing different approaches you might need to
docker-compose downto make sure Docker internally releases paths that are watched. - Remove junctions
.\remove_junctions.bat
You should notice that for every first directory/new 'common denominator' all events and changes to files/directories propagate correctly. Here an overview of what is expected, if we edit the existing file.txt in every respective subfolder.
| Directory | Change propagation | Note |
|---|---|---|
| a-dummy | ✔️ | |
| a-dummy2 | ❌ | Common denominator a-dummy |
| a-dummy3 | ❌ | Common denominator a-dummy |
| adummy | ✔️ | |
| adummy2 | ❌ | Common denominator adummy |
| aZZZdummy | ✔️ | |
| aZZZdummy2 | ❌ | Common denominator aZZZdummy |
| xdummy | ✔️ | |
| xdummyA | ❌ | Common denominator xdummy |
| z | ✔️ | |
| zdummyA | ❌ | Common denominator z |
| zdummyB | ❌ | Common denominator z |
Your console output should look a little bit like this (depending on the mechanism/command/editor used for changing files) if you go through the directories in alphabetical order:
inotify-monitor_1 | Setting up watches. Beware: since -r was given, this may take a while!
inotify-monitor_1 | Watches established.
inotify-monitor_1 | /mnt/self/junctions/a-dummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/a-dummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/adummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/adummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/aZZZdummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/aZZZdummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/xdummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/xdummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/xdummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/xdummy/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/z/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/z/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/z/ MODIFY file.txt
inotify-monitor_1 | /mnt/self/junctions/z/ MODIFY file.txt
We're missing several changes here.
This seems like a string comparison gone wrong, related to watched-paths checks inside Docker Desktop. This could also be an insufficient substr-comparison while iterating over those 'watched' junctioned directories, a dependency issue or something completely off. While changes propagate correctly, if the data/directories/files are fully 'self-contained' and you're either using junction targets that are inside the project root or no junctions at all, this issue comes into effect if the junction target itself (or a parent directory) is not bind-mounted explicitly.
You might also watch the com.docker.backend.exe.log in %APPDATA%\Docker\log\host which seems to list some interesting data and some erroneous looking entries related to startVolumeWatching and UnlockDirectories/LockDirectories.
These Docker-internal commands/code components are undocumented and might be closed source, it seems this not debuggable as a non-contributor.
adummy-targetdirs(dir) contains to-be-junctioned directoriesadummy-test(dir) is a docker-compose project rootadummy-test\Dockerfileis a custom Dockerfile providing inotifywait which recursively watches fs events inside the containeradummy-test\docker-compose.ymlgiving a minimal env that bind-mounts the directoryadummy-test\create_junctions.batcreates junctions for each directory in adummy-targetdirs respectively, e.g.adummy-test\junctions\a-dummy->..\adummy-targetdirs\a-dummyadummy-test\junctions\a-dummy2->..\adummy-targetdirs\a-dummy2and so on
adummy-test\remove_junctions.batremoves the created junctions by the previously mentioned bat fileadummy-selfcontainedis a variant (same data and containers, slightly different bind mounts) w/o junctioning directories outside the project root (regular way with same results)
A secondary container/service is available in the docker-compose.yml files, because inotifywait won't give you any results/events if your Docker version doesn't provide it. Therefore, I've provided a container that simply 'watches' using tail -F for every file.txt in every junctioned dir.