Postgres won't init: data directory permissions
Medium

Problem

A fresh postgres:15 won't stay up. It exits within seconds, every time. The compose file bind-mounts the data directory from the host (/srv/postgres-data), and the database was supposed to persist there.

The password env is set correctly and the image is fine — but the container keeps dying on startup. Read what postgres is actually complaining about and get a working database running with persistent storage.

Initial setup

  • dbpostgres:15, Exited (1), data dir bind-mounted from the host
path /srv/postgres-data.

Example interaction

$ docker logs db
chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted
...
initdb: error: could not change permissions of directory
"/var/lib/postgresql/data": Operation not permitted

$ docker inspect -f '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}}{{end}}' db
bind /srv/postgres-data -> /var/lib/postgresql/data

Acceptance

You've solved it when:

  • You've established that initdb failed because postgres (uid 999) cannot
own / set permissions on the mounted data directory (`Operation not permitted`) — a host volume ownership problem, not a bad password, a corrupt image, or a postgres bug.
  • You've brought a postgres container running on storage it can own —
e.g. a Docker-managed named volume (-v pgdata:/var/lib/postgresql/data), or the host dir after chown 999:999 /srv/postgres-data.

Constraints

  • Tools: docker CLI only.
  • End state: a postgres container in status == running with a data volume
it owns.

Follow-up

  1. Why does a Docker-managed named volume avoid this, while a bind mount
to an arbitrary host directory hits it?
  1. Which uid/gid must own the data dir for the official postgres image,
and how does the entrypoint try (and here fail) to set it?
  1. Why is chmod 777 on the data dir a tempting but wrong "fix"?
Live session
Code
SavedNo commands yet