Volumeshard5-8 years

A service's image ends with `USER app` (uid 10001). In development it's run with `-v $(pwd)/data:/app/data`, where `./data` was created by a plain `mkdir` as the developer's own user (uid 1000). The container gets `Permission denied` writing to `/app/data`. Why, precisely, and does switching to a named volume change anything?

A bind mount doesn't copy anything or translate ownership — /app/data inside the container and ./data on the host are the literal same inode, visible at two different paths, so the exact same Linux permission check applies to both. The directory is owned by uid 1000 (the developer, who ran mkdir); the process trying to write is running as uid 10001 (app, from the image's USER line), which has no write permission on a directory it doesn't own and that grants no group or other write bit. The container boundary is irrelevant to this check — it's exactly the same failure a host process running as a different uid would get writing into someone else's directory, because that's literally what's happening. A named volume changes the outcome because Docker creates and owns the backing directory itself and can set its ownership at creation time to whatever the container needs — there's no developer-owned host directory in the picture to conflict with in the first place.

The lesson behind it →