Home > Enterprise >  How to run postgres in docker as non-root user?
How to run postgres in docker as non-root user?

Time:09-12

I know that running docker containers as root is not secure, so I would like to change they way I run them. I have a container running postgres, which up till now was run as root (default). However, when I add this line to my docker-compose file:

user: ${CURRENT_UID}

Where CURRENT_UID is:

export CURRENT_UID=$(id -u):$(id -g)

I get the following error in the container logs:

initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted

fixing permissions on existing directory /var/lib/postgresql/data ... chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted

chmod: changing permissions of '/var/run/postgresql': Operation not permitted

The situation is the same when running the pg-admin container, with the error message:

PermissionError: [Errno 13] Permission denied: '/var/log/pgadmin'

The errors make sense of course, I am non root, yet postgres requires root access.

Does it mean it is impossible to run as non root?

CodePudding user response:

Does it mean it is impossible to run as non root?

In fact, the postgres service already runs as a non-root user. The startup process for the postgres container is effectively:

  1. Create necessary directories and set appropriate ownership
  2. Switch to the postgres user
  3. Start postgres

So if you start up the postgres image, even without specifying a user:

docker run -e POSTGRES_PASSWORD=secret postgres:14

You will find that it's running as the postgres user:

# ps -fe
UID          PID    PPID  C STIME TTY          TIME CMD
postgres       1       0  0 16:11 ?        00:00:00 postgres
postgres      56       1  0 16:11 ?        00:00:00 postgres: checkpointer
postgres      57       1  0 16:11 ?        00:00:00 postgres: background writer
postgres      58       1  0 16:11 ?        00:00:00 postgres: walwriter
postgres      59       1  0 16:11 ?        00:00:00 postgres: autovacuum launcher
postgres      60       1  0 16:11 ?        00:00:00 postgres: stats collector
postgres      61       1  0 16:11 ?        00:00:00 postgres: logical replication launcher

It is entirely possible to start the image as a non-root user as well, but in this case you have to ensure that the necessary directories exist and have appropriate ownership. In an environment like Kubernetes/OpenShift the container orchestration system will take care of this for you when mounting a volume, but when using plain Docker (or docker-compose) you have to take care of it yourself.

Here's one way of doing it:

  • Have an "initialization container" take care of setting volume permissions
  • Start postgres only after the initialization container has finished
version: "3.9"

services:
  postgres-init:
    image: postgres:14
    volumes:
      - "postgres_data:/data"
    entrypoint:
      - sh
      - -c
      - |
        chown -R 2000:2000 /data

  postgres:
    depends_on:
      postgres-init:
        condition: service_completed_successfully

    image: postgres:14
    environment:
      POSTGRES_PASSWORD: "secret"
      PGDATA: /pgdata
    volumes:
      - "postgres_data:/pgdata"
    user: "2000"

volumes:
  postgres_data:
  • Related