2

I'm trying to create PostgreSQL container with bind mounted host directory in it as the PostgreSQL data directory. Doing it according to official PostgreSQL docker image documentation and Example from Postres docker-library but stuck on error about initdb changing permissions.

$ ls -lan instance01/
total 8
drwxr-xr-x. 2 1004 1004 4096 Oct 13 23:49 .
drwx------. 7 1004 1004 4096 Oct 14 00:00 ..

passwd and group files are copied out from the image container and modified to add 1004:1004 as follows:

$ cat passwd_pg 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
postgres:x:999:999::/var/lib/postgresql:/bin/bash
foo:x:1004:1004::/var/lib/postgresql:/bin/bash


$ cat group_pg 
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
postgres:x:999:foo
foo:x:1004:foo
ssl-cert:x:101:postgres

User and group:

$ echo $(id -u):$(id -g)
1004:1004

Now creating the container:

$ podman container create --name postgres-instance01 -e POSTGRES_PASSWORD=test -p 5433:5432 --user $(id -u):$(id -g) --mount type=bind,relabel=private,ro=true,src=/home/foo/passwd_pg,dst=/etc/passwd --mount type=bind,ro=true,src=/home/foo/group_pg,dst=/etc/group,relabel=private --mount type=bind,src="/home/foo/instance01",relabel=private,dst=/var/lib/postgresql/data postgres:15

But when trying to run it the error shows:

$ podman container start -ai postgres-instance01
chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted
chmod: changing permissions of '/var/run/postgresql': Operation not permitted
The files belonging to this database system will be owned by user "foo".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted
1
  • That's probably (not in a location where I can test right now) because /var/lib/postgresql/data is the mount point. You'll have to state the desired permissions and uid/gid during the mount phase rather than later. Commented Oct 15 at 7:46

1 Answer 1

1

Adding the --userns=keep-id flag to your podman container create command solves the issue.

By default, rootless Podman containers operate within a user namespace. This means that your user ID (UID) and group ID (GID) on the host system are mapped to a different set of UIDs and GIDs inside the container. Typically, your host user is mapped to the root user (UID 0) inside the container.

Knowing this, using --user $(id -u):$(id -g) will not be enough. The process inside the container, running as what it thinks is your UID, is actually a different user from the host's perspective. When this process then tries to run chmod on the bind-mounted host directory, the kernel denies the operation because the actual owner of the directory is your host user, not the subordinate user the container process is running as.

And that's when --userns=keep-id kicks in. This flag simply makes sure that your host user's UID and GID are mapped to the exact same UID and GID inside the container.

Because the UIDs are now identical from the kernel's perspective, the initdb process running as 1004 inside the container has the correct ownership and permissions to read, write, and modify the instance01 directory mounted at /var/lib/postgresql/data.

And so, running with this flag, I got

podman container create --name postgres-instance01 -e POSTGRES_PASSWORD=test -p 5433:5432 --user $(id -u):$(id -g) --mount type=bind,relabel=private,ro=true,src=$PWD/passwd_pg,dst=/etc/passwd --mount type=bind,relabel=private,ro=true,src=$PWD/group_pg,dst=/etc/group --mount type=bind,relabel=private,src=$PWD/instance01,dst=/var/lib/postgresql/data --replace --userns=keep-id docker.io/library/postgres:15
0532053ac69c55153ef2cc07da9a1ea5170ea2b8a7329f5d3645685eafd6779a

podman container start -ai postgres-instance01
chmod: changing permissions of '/var/run/postgresql': Operation not permitted

2025-10-15 07:50:12.229 UTC [1] LOG:  starting PostgreSQL 15.14 (Debian 15.14-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
2025-10-15 07:50:12.230 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2025-10-15 07:50:12.230 UTC [1] LOG:  listening on IPv6 address "::", port 5432
2025-10-15 07:50:12.245 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2025-10-15 07:50:12.258 UTC [16] LOG:  database system was shut down at 2025-10-15 07:45:43 UTC
2025-10-15 07:50:12.266 UTC [1] LOG:  database system is ready to accept connections

The message chmod: changing permissions of '/var/run/postgresql': Operation not permitted is not fatal and will not stop podman to start. I can't continue to test right now but it is most likely because in the official PostgreSQL docker image, directories like /var/run/postgresql are created and owned by the postgres user, which has a standard UID of 999 creating a mismatch with your UID of 1004.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.