skip to content

A container process runs under a non-root numeric user id and gets permission denied writing to its mounted host directory — why?

level: middleimportance: must knowfreq 58%

answer

  1. numbers, not names
  2. the bits come through unchanged
  3. compare the process id to the owner
  4. no match falls through to others
  5. fix the directory's owner or group

basics

~20 s

Mounted storage keeps the ownership and mode bits it has outside the container, and the check compares numeric ids: if the process is neither the owner nor in the owning group, only the others bits apply — which rarely include write.

solid answer

~50 s

A mount does not change who owns the files. The directory carries a numeric owner, a numeric group and mode bits from the filesystem outside, and those come through the boundary unchanged. The filesystem then checks the writing process's own numeric id against them in order: owner first, then group, then everyone else — and it stops at the first one that applies. A directory owned by id `0` with `rwxr-xr-x`, mounted into a container whose process runs as id `10001`, therefore offers that process the others bits only: read and traverse, no write. The image's user name is irrelevant, because the filesystem stores numbers. The fix is to make storage and identity agree: pre-create the directory owned by that id, grant write to a group the process is in, or ask the platform for a volume and let it set ownership when it attaches.

code

pseudocode · 11 lines
pseudocode
process identity: user=10001 group=10001
mounted directory /work/output: owner=0 group=0 mode=rwxr-xr-x

open("/work/output/settlement.csv", write):
    if process.user == directory.owner:        # 10001 != 0
        decide using owner bits (rwx)          # not taken
    else if process.group == directory.group:  # 10001 != 0
        decide using group bits (r-x)          # not taken
    else:
        decide using others bits (r-x)         # taken: no write bit
            -> permission denied

go deeper

for a junior

Remember the shape of it: the mounted directory already has an owner and permission bits, and the process inside has to satisfy them just like any process. Nothing about being in a container makes a write allowed.

for a middle

Explain the ordered check — owner, then group, then others, stopping at the first match — and that names are resolved inside the image while the filesystem compares numbers. That is the mechanic this question is testing.

for a senior

Show that you plan the ownership contract, not just the error. Say which id writes, which ids read, who creates the directory, and why a provisioned volume whose ownership the platform sets at attach time is the version that survives a move.

for a principal

The trade-off is where identity for data is decided: in each image, in each machine's provisioning, or in the platform. Choosing the platform costs one convention and removes a recurring class of environment-specific failure from every team.

## The check that is actually failing A write is permitted or refused by the filesystem holding the data, using two facts: the **numeric user and group id the writing process runs as**, and the **ownership and mode bits recorded on the directory or file**. The evaluation is ordered and it stops at the first match: 1. If the process's user id equals the owner id, the **owner** bits decide — and nothing else is consulted. 2. Otherwise, if the process's group id (or one of its supplementary groups) equals the owning group, the **group** bits decide. 3. Otherwise the **others** bits decide. There is no fallback to a more generous rule when the first applicable set says no. An owner that is denied write does not then get to try the group bits. Mount that directory into a container and none of this changes. The boundary around a container gives the process its own **view** of the filesystem; it does not rewrite ownership on the way through. (Some platforms can be configured to remap ids between inside and outside — a distinct mechanism with a subject of its own.) So a directory owned by id `0` with mode `rwxr-xr-x`, mounted into a container whose process runs as id `10001`, presents that process with exactly the others bits: read and traverse, and no write. ## Numbers cross the boundary, names do not An image can declare that its process runs as a named account, but what reaches the filesystem is the **number** that name resolved to inside the image. The storage outside knows nothing about the container's account list, and two machines can perfectly well disagree about which name a given number belongs to. So: - the name in the image is a build-time convenience; the number is the runtime contract; - changing ownership *inside* the image changes image content, not the mounted directory, which is why rebuilding the image never fixes this; - the same image can succeed on one machine and fail on another purely because the directories were created by different things. ## The direction people forget: files going out The mismatch is symmetric. Files the job **creates** in a mounted directory carry the numeric id the process ran as, and the mode it created them with. That id may correspond to no account at all on the machine holding the storage. The consequences show up later, in somebody else's job: - a downstream task running as a different id cannot read the settlement file the batch produced; - an operator looking at the storage sees files owned by a bare number; - a tool that expects its own ownership refuses to process them. So the decision is not "how do I get past this error" but "which numeric id, and which mode, do all the readers and writers of this data agree on". ## Three honest fixes, and one non-fix | Approach | What it does | When it fits | |---|---|---| | Match the storage to the identity | create the directory owned by the id the process runs as, or grant write to a group it belongs to | a host path you control, where something reliably prepares the machine | | Let the platform set ownership | many platforms accept a declared owning group applied to a volume's contents when they attach it | the portable answer, and a practical reason to prefer a provisioned volume | | Write somewhere the workload owns | put the output on a volume attached for this workload rather than in a shared tree | whenever the shared tree is an input, not an output | | *Run the process as root* | makes the error disappear | it is not a fix: it discards the property the non-root id existed to provide, and the files it creates then carry root's ownership, handing the same argument to the next reader | ## Why the laptop was fine On a development machine the check passes by accident. The container often runs as a privileged id, or the directory was created by the same person who is now running the job, so owner or group matches without anyone deciding that it should. On a shared machine the workload is typically forced to a non-root id and the directory was created by something else entirely. The image did not change; the **identity** and the **directory's ownership** did, and neither of them is in the image. ## What a good answer sounds like Name the two sides of the comparison — the process's numeric id and the storage's owner, group and mode — say that a mount passes those bits through rather than rewriting them, and note that the check stops at the first applicable set. Then give the fix in terms of making the two agree, and mention that the same rule governs the ownership of what the job writes out, because that is where the problem usually reappears a week later.

  • How do you make the mounted directory writable without running the process as root?
    Make storage and identity agree. Pre-create the directory owned by the numeric id the process runs as, or grant write to a group that id belongs to. Where the platform provisions the volume, many platforms can apply a declared owning group to its contents at attach time — the portable version of the same fix.
  • The job writes its output fine, but the next task cannot read it. What is the likely cause?
    The output files carry the numeric id the job ran as and the mode it created them with. A second workload running as a different id, or a tool on the machine holding the storage, then has no access. Ownership crosses in both directions, so pick the owning id and mode once, for writers and readers together.
  • Why does rebuilding the image with different ownership not fix this?
    Ownership set during a build applies to image content. The mount overrides that path entirely, so the process sees the storage's own owner, group and mode instead. The only things the image contributes are the numeric id the process runs as and its group memberships.

saying these in an interview costs you the question

  • Blames the image's user name instead of the numeric id on disk.
  • Says the container boundary rewrites ownership on mounted files.
  • Thinks running as root is the only way to write a mounted directory.
  • Assumes new files take the directory's owner rather than the writing process's.
  • Believes fixing ownership inside the image changes the mounted directory.
  • Expects the permission bits inside the container to differ from those outside.