From b37740bcce322af82b47f2c3e0cc86e82f13fd26 Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Thu, 23 Apr 2026 00:27:07 +0200 Subject: [PATCH] Fix incorrect 'Linux unaffected' claim in bind-mount caveat The previous note scoped the single-file bind-mount staleness bug to Docker Desktop only. It actually affects ALL platforms including native Linux: Docker bind-mounts the inode, not the path. Editors that do atomic save (vim, nvim, VS Code, sed -i) create a new inode via rename(), leaving the container pinned to the old unlinked one. This is a kernel limitation (moby/moby#15793, open since 2015, unfixable). Rewrite both the README.md caveat and the docker-compose.yml inline note to describe the real mechanism (inode replacement), name the affected editors, note that append-only writes are safe, and link to the upstream issue. --- README.md | 2 +- docker-compose.yml | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f95d486..3d00090 100644 --- a/README.md +++ b/README.md @@ -466,7 +466,7 @@ Defaults you get out of the box: - ~/.inputrc:/home/developer/.inputrc:ro ``` -> **Docker Desktop caveat (macOS/Windows):** Single-file bind-mounts can silently stop propagating host edits — Docker Desktop materializes the file onto the VM's disk on first mount, and later host changes never reach the container. Verify with `docker compose exec devbox mount | grep bash_aliases` — a live share shows a `grpcfuse`/`virtiofs` source; a broken one shows `/dev/vda1`. Workaround: use a directory mount instead (`~/.config/devbox-shell:/home/developer/.config/devbox-shell:ro`) and source files from there. Linux hosts are unaffected. +> **Single-file bind-mount caveat (all platforms):** Docker bind-mounts the file's **inode**, not its path. When editors like vim, nvim, VS Code, or `sed -i` save a file, they write to a temp file and `rename()` it over the original — creating a new inode. The container stays pinned to the old (now unlinked) inode and never sees the update. This is a kernel limitation ([Docker #15793](https://github.com/moby/moby/issues/15793)), not fixable by Docker. Append-only writes (`echo "alias foo=bar" >> file`) are safe because they modify the same inode. **Workaround:** mount the parent directory instead of the single file (e.g. `~/.config/devbox-shell:/home/developer/.config/devbox-shell:ro`) and source files from there. **Option B — customize inside the container.** Just edit `~/.bash_aliases` or `~/.inputrc` as normal. Pair this with a bind-mount or named volume on the home dir if you want the edits to survive container recreation. diff --git a/docker-compose.yml b/docker-compose.yml index 9040af4..2bbff22 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -65,10 +65,12 @@ services: # The image ships sensible defaults (history tuning, prefix-search on # Up/Down arrows, fzf/zoxide integration). Uncomment to use your own: # - # NOTE: On Docker Desktop (macOS/Windows), single-file bind-mounts can - # silently stop propagating host edits — the file gets materialized onto - # the VM disk. If host changes don't appear in the container, see the - # "Shell defaults" section in README.md. Linux hosts are unaffected. + # NOTE: Single-file bind-mounts break when editors use atomic save + # (vim, VS Code, sed -i write a temp file then rename() over the + # original, creating a new inode the container never sees). This is a + # kernel limitation, not Docker-specific. If host edits stop appearing + # in the container, mount the parent directory instead — see the + # "Shell defaults" section in README.md. # - ~/.bash_aliases:/home/developer/.bash_aliases:ro # - ~/.inputrc:/home/developer/.inputrc:ro