docker-library / postgres

Docker Official Image packaging for Postgres
http://www.postgresql.org
MIT License
2.16k stars 1.13k forks source link

associate --user id with the internal postgres user id #1260

Closed gertcuykens closed 1 month ago

gertcuykens commented 1 month ago

Allow --user to determine all file permissions for example /var/run/postgresql not only pgdata So you can do -v of the unix socket representing the --user permissions

yosifkit commented 1 month ago

The image is designed to allow running as any --user; we set the permissions of directories so that works:

https://github.com/docker-library/postgres/blob/66da3846b40396249936938ee17e9684e6968a57/Dockerfile-debian.template#L10 https://github.com/docker-library/postgres/blob/66da3846b40396249936938ee17e9684e6968a57/Dockerfile-debian.template#L181 https://github.com/docker-library/postgres/blob/66da3846b40396249936938ee17e9684e6968a57/Dockerfile-debian.template#L185

tianon commented 1 month ago

I'm sorry, can you please elaborate? I just tested arbitrary user recently, and it was working OK, but maybe there's something you're doing differently that could help explain why it isn't working for you?

tianon commented 1 month ago

(If you've bind-mounted or volume-mounted a directory, it won't usually use the permissions of the directory in the image anyhow, so you'll need to also arrange to fix the permissions of your volume/directory beforehand, because without running the image as root, we can't do anything from the image to fix it for you.)

gertcuykens commented 1 month ago
docker run --name postgres --user root --restart unless-stopped \
  -e POSTGRES_PASSWORD="hello" \
  -e LANG=C.UTF-8 \
  -e LC_ALL=C.UTF-8 \
  -v postgres:/var/lib/postgresql/data \
  -v /var/run/postgresql:/var/run/postgresql \
  --shm-size=128m \
  --init -d postgres

This will result in a socket volume with the postgres permission id 999 from with in the container instead of the user root id 0

image

I expect the socket to be root (the --user) instead, thanks

tianon commented 1 month ago

Oh, running PostgreSQL itself as root is not something we or PostgreSQL support, IIRC. :grimacing:

Your best bet to play with this would be to bypass our entrypoint entirely, but last time I tried that PostgreSQL balked very loudly and early.

tianon commented 1 month ago

To illustrate:

$ docker run -it --rm --pull=always --user root --entrypoint postgres postgres
latest: Pulling from library/postgres
Digest: sha256:0aafd2ae7e6c391f39fb6b7621632d79f54068faebc726caf469e87bd1d301c0
Status: Image is up to date for postgres:latest
"root" execution of the PostgreSQL server is not permitted.
The server must be started under an unprivileged user ID to prevent
possible system security compromise.  See the documentation for
more information on how to properly start the server.
tianon commented 1 month ago

Perhaps you can get closer to what you're looking for via https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-UNIX-SOCKET-GROUP and/or https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-UNIX-SOCKET-PERMISSIONS ?

gertcuykens commented 1 month ago

ok thanks i will look into this but i assume even if you would create a --user postgres on the system then it still will be 999 right? Which always will clash with systemd-journal group on debian bookworm, because 999 is hardcoded in the Dockerfile related to the socket

https://github.com/docker-library/postgres/blob/66da3846b40396249936938ee17e9684e6968a57/Dockerfile-debian.template#L5-L10

So the question would boil down to if 999 can be replaced with the id from --user x ?

yosifkit commented 1 month ago

So the question would boil down to if 999 can be replaced with the id from --user x ?

To use any arbitrary user ID, you must provide directories with the appropriate permissions (so, whether you use a docker volume or a local directory it might need a chown/chmod performed before being given to the postgres server container). Here is an example using local directories for data and run with my local user ID:

$ mkdir data
$ mkdir postgresql-run
$ ls -lna data/ postgresql-run/
data/:
total 8
drwxr-sr-x 2 1000 1000 4096 Jul 11 15:25 .
drwxrwsr-x 8 1000 1000 4096 Jul 11 15:25 ..

postgresql-run/:
total 8
drwxr-sr-x 2 1000 1000 4096 Jul 11 15:25 .
drwxrwsr-x 8 1000 1000 4096 Jul 11 15:25 ..
$ docker run -it --rm --name postgres \
  -e POSTGRES_PASSWORD="hello" \
  -e LANG=C.UTF-8 \
  -e LC_ALL=C.UTF-8 \
  -v "$PWD/data":/var/lib/postgresql/data \
  -v "$PWD/postgresql-run":/var/run/postgresql \
  --shm-size=128m \
  --user 1000:1000 \
  postgres
...
2024-07-11 22:26:38.215 UTC [1] LOG:  database system is ready to accept connections

$ # another terminal
$ ls -lna data/ postgresql-run/
data/:
total 136
drwx------ 19 1000 1000  4096 Jul 11 15:26 .
drwxrwsr-x  8 1000 1000  4096 Jul 11 15:25 ..
drwx------  5 1000 1000  4096 Jul 11 15:26 base
drwx------  2 1000 1000  4096 Jul 11 15:26 global
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_commit_ts
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_dynshmem
-rw-------  1 1000 1000  5743 Jul 11 15:26 pg_hba.conf
-rw-------  1 1000 1000  2640 Jul 11 15:26 pg_ident.conf
drwx------  4 1000 1000  4096 Jul 11 15:26 pg_logical
drwx------  4 1000 1000  4096 Jul 11 15:26 pg_multixact
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_notify
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_replslot
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_serial
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_snapshots
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_stat
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_stat_tmp
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_subtrans
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_tblspc
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_twophase
-rw-------  1 1000 1000     3 Jul 11 15:26 PG_VERSION
drwx------  3 1000 1000  4096 Jul 11 15:26 pg_wal
drwx------  2 1000 1000  4096 Jul 11 15:26 pg_xact
-rw-------  1 1000 1000    88 Jul 11 15:26 postgresql.auto.conf
-rw-------  1 1000 1000 29753 Jul 11 15:26 postgresql.conf
-rw-------  1 1000 1000    36 Jul 11 15:26 postmaster.opts
-rw-------  1 1000 1000    94 Jul 11 15:26 postmaster.pid

postgresql-run/:
total 12
drwxrwsr-t 2 1000 1000 4096 Jul 11 15:26 .
drwxrwsr-x 8 1000 1000 4096 Jul 11 15:25 ..
srwxrwxrwx 1 1000 1000    0 Jul 11 15:26 .s.PGSQL.5432
-rw------- 1 1000 1000   63 Jul 11 15:26 .s.PGSQL.5432.lock
gertcuykens commented 1 month ago

You are right, that works for me too, follow up question, can the postgres user be associated then with the --user id (in this case 1000)?

docker exec -it postgres /bin/bash

I have no name!@060c23ea2c69:/$ id
uid=1000 gid=1000 groups=1000

I have no name!@060c23ea2c69:/$ cat /etc/passwd
...
postgres:x:999:999::/var/lib/postgresql:/bin/bash

I have no name!@060c23ea2c69:/$ cat /etc/group
...
postgres:x:999:
ssl-cert:x:101:postgres
docker exec -it postgres psql -U postgres postgres

psql (16.3 (Debian 16.3-1.pgdg120+1))
Type "help" for help.

postgres=#
\q
could not save history to file "//.psql_history": No such file or directory
gertcuykens commented 1 month ago

Maybe just add ARG UID="999" in the Dockerfile and use $UID where 999 is hardcoded?

yosifkit commented 1 month ago

No, we don't edit /etc/passwd (especially as a non-root user) to change the ID of the postgres user. You could provide a custom /etc/passwd by COPY or bind mount (read only, if using your system one) that has the user ID and name you desire. If the psql history file is important to you then setting HOME to a place that your custom user ID can write is the fix (like the /var/lib/postgresql that is set for postgres).

As for ARG UID="999", that would require a user to rebuild the whole postgres image to customize an ID, instead of just being FROM it. We don't typically put that sort of customization into the Dockerfile because it just leads to code paths in the Dockerfile that we never use. We'd rather that users build FROM postgres:version and add their customization on top.

gertcuykens commented 1 month ago
FROM postgres:16 AS postgres16
ARG DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
RUN apt update && apt upgrade -y
RUN apt install -y man-db vim curl ca-certificates && update-ca-certificates
RUN apt install -y python3-psutil postgresql-plpython3-16
RUN apt autoremove -y --purge && apt clean -y \
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf /tmp/* \
    && rm -rf /var/tmp/*
RUN usermod -u 1000 postgres
RUN groupmod -g 1000 postgres
HEALTHCHECK --interval=60s --timeout=3s --retries=1 CMD pg_isready -U postgres
WORKDIR /var/lib/postgresql
USER postgres

alright good enough for me closing