Docker Rootless Build - "permission denied" Writing Files in CI
In rootless Docker the daemon runs in a user namespace, so container root maps to your unprivileged host user. Operations that assume real root - writing host-owned paths, binding low ports, certain mounts - get "permission denied" that the same image avoids under a rootful daemon.
What this error means
A build or run under rootless Docker fails with permission denied writing a file, binding a port below 1024, or performing a mount - while the identical Dockerfile/command works on a normal rootful daemon.
# rootless: container UID 0 maps to an unprivileged host UID
cp: cannot create regular file '/output/app': Permission denied
# or: failed to bind host port 0.0.0.0:80: permission deniedCommon causes
uid/gid remapping under the user namespace
Rootless maps container uids to a subuid/subgid range on the host. Files written to host-mounted paths get unexpected ownership, and reads/writes of host-owned files can be denied.
Privileged operations the rootless daemon cannot do
Binding ports below 1024, some mounts, and certain capabilities require real privilege the rootless daemon does not have, surfacing as "permission denied".
subuid/subgid range too small or unset
If the host user lacks a sufficient /etc/subuid//etc/subgid range, the namespace cannot map the ids the image needs.
How to fix it
Map ownership for host-mounted paths
Account for the uid remapping when writing to bind mounts, or write to a named volume the daemon owns.
# ensure the host user has a subuid/subgid range:
grep "$USER" /etc/subuid /etc/subgid
# prefer named volumes (owned by the rootless daemon) over host binds:
docker volume create out
docker run -v out:/output myorg/apiAvoid privileged ops or use a rootful daemon
- Publish high ports (>=1024) instead of privileged low ports under rootless.
- Enable port forwarding via slirp4netns/rootlesskit where needed.
- For builds that genuinely need root-level operations, run on a rootful daemon instead.
How to prevent it
- Design images to write to volumes the rootless daemon owns, not host paths.
- Use high ports under rootless, or configure rootless port forwarding.
- Provision adequate subuid/subgid ranges for the runner user.