Volume mount UID/GID permission mismatches

When a container writes to a bind mount, it writes as the UID inside the container. If that UID doesn’t match the owner of the host directory, you get permission denied errors — or worse, files owned by root on the host.

The problem

A container running as UID 1000 writes to /data. On the host, /data is owned by your user (also UID 1000) — no problem. But many service images run as a custom UID (e.g., UID 999 for postgres, UID 568 for some linuxserver.io images). The container writes fine, but the host sees files owned by an unknown UID.

linuxserver.io PUID/PGID

Most linuxserver images accept PUID and PGID environment variables that remap the internal service user to a UID/GID you control:

environment:
  - PUID=1000
  - PGID=1000

Set these to match your host user (id -u / id -g).

Fixing ownership manually

# Find your UID
id -u   # e.g. 1000

# Fix existing files
sudo chown -R 1000:1000 /path/to/volume

# Or fix from inside the container
docker run --rm -v /path/to/volume:/data alpine chown -R 1000:1000 /data

Named volumes

Named volumes (managed by Docker) don’t have this problem when accessed only from containers — Docker manages the path. It surfaces when you try to access a named volume from the host directly (/var/lib/docker/volumes/...), which you generally shouldn’t do.

The USER directive

If you control the Dockerfile, set the runtime user explicitly:

RUN addgroup -S app && adduser -S app -G app
USER app

This prevents the container from running as root and makes volume ownership predictable.