88 lines
4.8 KiB
Markdown
88 lines
4.8 KiB
Markdown
# Fix slow/failing `chown -R` in entrypoint.sh on Mac ARM bind mounts
|
|
|
|
## Context
|
|
|
|
On macOS (Apple Silicon), Docker Desktop bind-mounts host project folders (e.g.
|
|
`/home/aleleba/projects/telus/telus-board-report`) into the container over a virtualized
|
|
filesystem (virtiofs/gRPC-FUSE) that does not support changing file ownership from inside
|
|
the container. `entrypoint.sh:79` runs:
|
|
|
|
```bash
|
|
sudo chown -R ${HOME_USER} /home/${HOME_USER}
|
|
```
|
|
|
|
This recurses into those bind-mounted directories too, including huge `node_modules`
|
|
trees, and every single file inside them fails with `Operation not permitted`. Two real
|
|
problems come from this, not just one:
|
|
|
|
1. **Speed** — `chown -R` walks every file individually; over tens of thousands of
|
|
`node_modules`/`.venv` entries this is very slow.
|
|
2. **Correctness (bigger issue found during investigation)** — the script starts with
|
|
`set -eu`. `chown -R` still returns a non-zero exit status once it finishes (even
|
|
though it keeps going and reports every failure), and this line is not guarded by
|
|
`|| true` or an `if`. Confirmed locally: a failing `chown` under `set -e` aborts the
|
|
script immediately at that line. That means once this line fails, **everything after
|
|
it in entrypoint.sh never runs** — no `.ssh` permission fixup, no custom-scripts, no
|
|
extension install, and critically the final `code tunnel ...` command that actually
|
|
starts the VS Code tunnel. So this isn't just "slow," it can silently prevent the
|
|
container from ever reaching the tunnel start step on a run where a permission error
|
|
occurs.
|
|
|
|
The user has confirmed ownership doesn't actually need to change on these mounted
|
|
folders — the Dockerfile already does `chmod -R a+rwX /home` at build time (`Dockerfile:41`),
|
|
and the host-mounted files are already world-writable (777), so `aleleba` can read/write
|
|
them regardless of `chown` succeeding.
|
|
|
|
## Fix
|
|
|
|
Edit `entrypoint.sh:79`, replacing the whole-home recursive `chown` with a `find -xdev`
|
|
based version that:
|
|
|
|
- **Stays on the container's own filesystem** (`-xdev`) so it never descends into
|
|
separately-mounted bind volumes like `/home/${HOME_USER}/projects/...` — this is what
|
|
fixes the slowness, without hardcoding folder names like `node_modules`/`.venv`
|
|
(it works generically for any bind-mounted subtree, not just those two).
|
|
- **Never aborts the script** even if an unexpected chown failure occurs elsewhere, by
|
|
appending `|| true` (this is the correctness fix — restores the guarantee that the
|
|
rest of entrypoint.sh, including the VS Code tunnel startup, always runs).
|
|
|
|
```bash
|
|
sudo find "/home/${HOME_USER}" -xdev -exec chown "${HOME_USER}" {} + 2>/dev/null || true
|
|
```
|
|
|
|
This is a single-line change to `entrypoint.sh`; no other recursive chown/chmod calls in
|
|
the script (lines 72, 132, 137, 142) are touched, since those aren't the ones hitting
|
|
bind-mounted project directories.
|
|
|
|
**This is not a Mac-only fix.** `-xdev` skips any directory that is a separate mount
|
|
point (different device id) from `/home/${HOME_USER}` itself — that's true for bind
|
|
mounts on Linux/Synology just as much as on macOS. The difference is only in symptom:
|
|
- On **macOS** (virtiofs/gRPC-FUSE), `chown` on the bind-mounted files fails outright
|
|
(`Operation not permitted`), which — combined with the `set -e` bug above — can abort
|
|
the whole entrypoint before the tunnel starts.
|
|
- On **Linux**, the same `chown -R` walk into `node_modules`/`.venv` succeeds file-by-file
|
|
(root can chown across a Linux bind mount), so there's no error output, but it still
|
|
pays the same per-file syscall cost — this is almost certainly why the user's other,
|
|
working Linux/Synology environment is *also* slow to start, just silently.
|
|
|
|
Because the fix skips crossing the mount boundary rather than special-casing specific
|
|
folder names or the host OS, one change fixes both the correctness bug (Mac) and the
|
|
startup latency (all environments) with no behavior change for anything that lives on
|
|
the container's own filesystem (`.ssh`, dotfiles, `.vscode*`, etc. are chowned exactly as
|
|
before).
|
|
|
|
## Verification
|
|
|
|
1. Read the diff to confirm only line 79 changed and the semantics (still chowning to
|
|
`HOME_USER`, still running as root via `sudo`) are preserved.
|
|
2. Locally simulate the `set -e` abort scenario (same repro used during investigation:
|
|
a `chown -R` hitting a permission-denied/missing path under `set -eu` kills the
|
|
script) and confirm the new `find -xdev ... || true` line does **not** abort a
|
|
`set -eu` script even when it encounters a permission error.
|
|
3. Rebuild the image (`docker build .`) to confirm the Dockerfile/entrypoint still builds
|
|
cleanly.
|
|
4. If possible, run the container with a bind-mounted `node_modules`-heavy directory
|
|
(mirroring the user's Mac setup) and confirm: no `Operation not permitted` spam, the
|
|
entrypoint completes quickly, and the `code tunnel` command still launches at the end
|
|
of the log.
|