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:
- Create necessary directories and set appropriate ownership
- Switch to the
postgres
user - 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: