Coding Agents & Terminal · recorded 2026-08-29 · applies to 1 tool(s) ✓ Verified

Problem: Container can see the mount but reads/writes fail with Permission denied (uid mismatch) —— Trove problem library

Verified 2026-08-29bind-mount permission denied — chown the host dir to the container uid (chown -R 1000:1000), or run with -u 1000:1000.

Quick fix

# One-liner: chown the host directory to the in-container uid (example: container uid 1000)
sudo chown -R 1000:1000 ./data && docker run --rm -u 1000:1000 -v "$PWD/data:/data" <image> ls /data

What you will run into

The container starts fine and the mount is visible (ls shows files), but any process read/write fails with Permission denied.

You think the mount didn't work — it did; the real issue is the uid of the process inside the container doesn't match the owner of the host directory.

Common trigger: switching to a non-root user per security advice (-u 1000:1000, compose user:, or an image built-in USER). Everything works when the image runs as root by default; the problem appears immediately after the switch.

Why this happens

Linux permissions match by uid/gid, and bind mounts don't translate ownership: the container process's uid is judged directly against the host directory file's owner/permissions.

Typical mismatch: host files owned by root (uid 0), container process runs with a non-zero uid → reading 600 files is denied, writes fail.

Common misconception: switching to a named volume doesn't auto-fix it either — docker initializes a new named volume's directory as root:root 755, and a non-root container still gets Permission denied (measured reproduction).

Linux permission checks match "process uid/gid × file owner/mode bits".

A bind mount just attaches the host directory into the container — no uid mapping and no ownership translation: a uid-1000 process inside the container reading a host 0600 file owned by uid 0 is judged exactly like a normal host user reading a root file.

On first creation, a named volume is initialized to root:root 755, so non-root containers hit Permission denied with named volumes too.

Deterministic takeaway: do not guess "it should be writable inside the container" — first run docker run --rm -v <dir>:/data <image> ls -ln /data to see the real owner;

then pick one of three fixes: chown -R 1000:1000 on the host to align uids, run the container as root (temp/dev), or user-namespace remapping (production).

chown changes the host files, so both sides take effect at once.

Step by step

1. Confirm it's permission, not the mount — Required

docker run --rm -u 0:0 -v "$PWD/data:/data" <image> ls -l /data

A root container can read it, a non-root container can't → permission problem (measured comparison).

2. Adjust the host directory owner — Required

sudo chown -R 1000:1000 ./data

chown to the in-container uid — a one-time fix, suitable when the data directory's owner is stable (measured: after chown, the non-root container reads successfully, exit 0).

3. With an image built-in user, check the official docs — Required

Many official images state "please run with -u 1000:1000" (e.g. blocky's internal user is uid 100); align with the docs, don't guess.

4. Named volume permission initialization — Required

If the image's target directory owner doesn't match, chown in the entrypoint / an init container; only when the image directory owner is already correct (e.g. the image creates /data owned by 1000) can you rely on volume auto-initialization.

5. Temporary emergency escape — Required

-u 0:0 runs the container as root and bypasses this, but it breaks least-privilege; local debugging only.

How to confirm it works

docker run --rm -u 1000:1000 -v "$PWD/data:/data" <image> touch /data/write-test && echo OK

A successful write means it's fixed.

Measured: -u 1000:1000 reading a root-owned 600 file → Permission denied (exit 1); root container reading the same mount → success; after host chown 1000:1000 the non-root container → success;

named volume initialized with owner root:root 755, non-root container touch → still Permission denied (misconception confirmed).

Other environments

EnvironmentNotes
Bind mount (-v host:container)Most typical; chown the host directory to align uids
Named volumeDoesn't auto-fix; works only if the image's directory owner is correct
Docker Desktop (Windows/macOS)Also common; mounted directory owner mismatches the container uid
Image built-in USERCheck the official recommended -u, align with docs

Symptom

The container starts fine and the mount is visible (ls shows files), but any read/write by the process fails:

cat: can't open '/data/rootfile': Permission denied
touch: /data/write-test: Permission denied
mkdir: cannot create directory '/data/xxx': Permission denied
cannot create temp cache file in /cache: open /cache/xxx.tmp: permission denied

Key traits:

  • Container runs and the directory is visible — only read/write is denied, easily mistaken for "the mount failed";
  • Typical with non-root containers: image USER, docker run -u UID:GID, or compose user: "1000:1000";
  • Bind mounts (-v /host/path:/container/path) are the most common case; named volumes can hit it too;
  • Docker Desktop on Windows/macOS hits it frequently (host directories whose owner doesn't match the container uid).

Cause

Linux permissions match by uid/gid, and bind mounts do no ownership translation: the container process's uid is checked directly against the host file's owner/permissions. The classic mismatch is host files owned by root (uid 0) or another uid (e.g. 1000) while the container process runs as a non-zero uid → can't read 600 files / can't write. Everything works while the image runs as root; the problem appears the moment you switch to a non-root user for security.

Common misconception: switching to a named volume does not fix it automatically — docker initializes a new named volume as root:root 755, so a non-root process still can't write (unless the target directory inside the image already belongs to that uid).

Solution

  1. Align the container uid with the host (recommended): docker run -u "$(id -u):$(id -g)" -v "$PWD/data:/data" ... — the process runs as your host uid and can read/write its own files; in compose use user: "${UID}:${GID}" (export UID/GID in the shell).
  2. Fix the host directory ownership: sudo chown -R 1000:1000 ./data (chown to the container's uid) — a one-time fix for directories with a fixed owner.
  3. If the image has a built-in user, read its docs: official images usually state the exact run command (e.g. blocky runs as uid 100) — align with the documented uid instead of guessing.
  4. Named-volume permission init: if the image's target directory owner doesn't match, chown in the entrypoint / an init container; only if the image directory is already owned correctly can you rely on docker's automatic volume initialization.
  5. Quick workaround: -u 0:0 runs the container as root and bypasses the issue, but breaks least-privilege — local debugging only.
Verification Evidence
  • Local repro (2026-08-29, WSL Ubuntu, docker 29.1.3, alpine:3.20):
  • Setup: a host file owned by root (uid 0) with mode 600;
  • Repro: docker run --rm -u 1000:1000 -v /tmp/vol-test:/data alpine cat /data/rootfile → Permission denied (exit 1);
  • Control: root container (no -u) reading the same mount → success (mount itself is fine);
  • Fix A: host chown 1000:1000 → non-root container reads it → success (exit 0);
  • Fix B: -u 0:0 aligned with host → success (exit 0);
  • Misconception check: after docker volume create, a -u 1000:1000 container touching the named volume → Permission denied (exit 1); ls -ld /data confirms the volume initialized as root:root 755 → named volumes do NOT auto-fix permissions; a root container writing the same named volume → success.

Evidence details kept locally (2026-08-29)

Related canonicals

Read in order: precondition -> same root / same domain / related:

Applicable tools (1)

This problem is linked from the tool pages below — reachable from either side.

docker

Bundled solutions (combos)

This problem is part of the following verified bundles.

Source & evidence

Recorded Verified ✓ VerifiedApplies to 1 tool(s)
Entries contain locally measured or reviewable-source solutions; unmeasured items are explicitly labeled.

Source: https://github.com/0xERR0R/blocky/issues/2165

← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk