CertGrid CertGrid
Troubleshooting·Podman

Rootless Podman Build UID Limits

`RUN chown 65000:65000` builds fine and `RUN chown 70000:70000` fails with `Invalid argument`, because /etc/subuid grants you exactly 65536 subordinate UIDs. The limit is a number you can read off your own host.

Building Images Guide 20 of 47 Advanced

Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.

Every command on this page ran on podman01.
Server NameIP AddressOSRolesCPURAMHDD
PODMAN01192.168.0.24Ubuntu 26.04 LTSPrimary Container Host2 Core4 GB50 GB

Before you start

  1. A chown that works

    A two-instruction Containerfile that changes the ownership of /tmp to UID 65000, a user that does not exist and does not need to.

    It builds. uid 65000 inside range: ok.

    Nothing surprising yet - but it is worth establishing that arbitrary chown inside a rootless build works at all, because the reflex explanation for the failure in the next step is "rootless cannot chown", and that is wrong.

    bash Example session
    mkdir -p ~/limits && cd ~/limits && cat > Containerfile <<'CF'FROM docker.io/library/alpine:3.22RUN chown 65000:65000 /tmp && echo "uid 65000 inside range: ok"CFcd ~/limits && podman build -t limits:inrange .STEP 1/2: FROM docker.io/library/alpine:3.22STEP 2/2: RUN chown 65000:65000 /tmp && echo "uid 65000 inside range: ok"uid 65000 inside range: okCOMMIT limits:inrange--> 20ff7e5ae9b5Successfully tagged localhost/limits:inrange20ff7e5ae9b58de4fcb1183a64ec345b0208d0cb1a0d0e6c4922ed08c4d8e4e6

    Expected resultA successful build printing uid 65000 inside range: ok.

    Success conditionYou have chowned to a high, nonexistent UID in a rootless build.

  2. The same instruction, a bigger number, a failed build

    Change 65000 to 70000 and nothing else:

    STEP 2/2: RUN chown 70000:70000 /tmp && echo "..."
    chown: /tmp: Invalid argument
    Error: building at STEP "RUN chown 70000:70000 /tmp ...": while running
    runtime: exit status 1

    Exit 1, no image. And note the error is Invalid argument, not Permission denied - which is the clue. Permission denied would mean you are not allowed to do it. Invalid argument means the UID does not exist as far as this namespace is concerned: there is no mapping for it, so it is not a number that can be written into an inode here.

    The answer is in one line of /etc/subuid:

    sysadmin:100000:65536

    65536 subordinate UIDs, starting at host UID 100000. Inside the build's user namespace they appear as 1 to 65536, with 0 mapped to your own account. 65000 is inside that window. 70000 is past the end of it, and no amount of privilege inside the container invents a mapping that the kernel was not given.

    So the limit is arithmetic you can do on any host: read the count from /etc/subuid and that is the highest UID your rootless builds can name.

    bash Example session
    mkdir -p ~/limits && cd ~/limits && cat > Containerfile <<'CF'FROM docker.io/library/alpine:3.22RUN chown 65000:65000 /tmp && echo "uid 65000 inside range: ok"CFcd ~/limits && podman build -t limits:outofrange .STEP 1/2: FROM docker.io/library/alpine:3.22STEP 2/2: RUN chown 70000:70000 /tmp && echo "uid 70000 should not be reachable"chown: /tmp: Invalid argumentError: building at STEP "RUN chown 70000:70000 /tmp && echo "uid 70000 should not be reachable"": while running runtime: exit status 1[exit 1]cat /etc/subuidsysadmin:100000:65536

    Expected resultchown: /tmp: Invalid argument, a failed build, and a subuid range of 65536.

    Success conditionYou can compute your own host's ceiling from /etc/subuid.

  3. What to do about it

    This is not a theoretical limit. Images that create a user at a very high UID hit it, and so does anything unpacking an archive that records high ownership - some enterprise base images use UIDs in the millions specifically to avoid collisions on shared hosts.

    Four options, in the order worth trying:

    1. Use a lower UID. If the number is arbitrary - and it usually is - anything under 65536 works and nothing is lost.
    2. Widen the range. sudo usermod --add-subuids 200000-2000000 --add-subgids 200000-2000000 $USER, then podman system migrate. This is the right fix when the UID is not yours to choose, and it needs root once.
    3. Build rootful. sudo podman build has the whole UID space - and lands the image in root's store, which is a different machine as far as your account is concerned (guide 14).
    4. Question the UID. A base image needing a UID in the millions inside a container that already has its own namespace is usually solving a problem you do not have.

    The wider point for the rest of this path: rootless is not a restricted mode with arbitrary rules. Every limit it has follows from the UID mapping, and each one can be traced back to a number in /etc/subuid. When something fails rootless and the message mentions UIDs, that is the file to read.

    bash Example session
    cat /etc/subuidsysadmin:100000:65536

    Expected resultThe single line that defines the ceiling.

    Success conditionYou can choose between lowering the UID and widening the range, with a reason.

Troubleshooting

Official sources