Create a Docker-Postgres-Container on Linux with docker-compose and a bind-mount, such that the dir contains the pgres-data and is not owned by root

Published

This question has been asked countless times in countless places, but so far, I haven’t found a single answer that actually works.

What I want:

I want to create a Docker-Container (using Docker-Compose and only a single startup without manually having to chmod or chown in between), that contains a Postgres-Database. The contents of this database should be bind-mount to my local system, eg. to the directory ./data, as would theoretically be possible using volumes:n ./data:/var/lib/postgresql/data. If one das that, however, the ./data directory will be owned by root (or by systemd-coredump because that’s the user with the id 999), and I don’t want that. I want to be able to move the whole thing to another location without root-rights, so the resulting directory should be owned by my user (1000:1000).

This has been asked countless times, but no answer I tried worked. Either the directory created was empty on the host (presumably because the container didn’t have rights to write as my user), or it was only accessible by root, or it would have worked with a volume (!=bind-mount), or it would have worked when chown-ing in between, but that’s all not what I want.

What I found so far:

https://github.com/docker-library/postgres/issues/116: None of these solutions worked for me.

  • when I eg. run PG_DATA=$(pwd)/data docker run -d --name psql -e POSTGRES_PASSWORD=DB_PASS -e POSTGRES_USER=DB_USER -e POSTGRES_DB=DB_NAME -e PGDATA=$PG_DATA -v $PG_DATA:/var/lib/postgresql/data postgres:11.5-alpine (krzysztof-adamski‘s solution), the ./data directory stays empty on my host.
  • shewless‘s solution also doesn’t work:
    • docker run -it --rm --user "$(id -u):$(id -g)" -v $(pwd)/data:/var/lib/postgresql/data -v /etc/passwd:/etc/passwd:ro -e POSTGRES_PASSWORD=mysecretpassword -e PGDATA=/var/lib/postgresql/data/mydata postgres returns mkdir: cannot create directory ‘/var/lib/postgresql/data/mydata’: Permission denied
    • while docker run -it --rm --user "$(id -u):$(id -g)" -v $(pwd)/data:/var/lib/postgresql/data/pgdata -v /etc/passwd:/etc/passwd:ro -e POSTGRES_PASSWORD=mysecretpassword -e PGDATA=/var/lib/postgresql/data/pgdata postgres gives me the error chmod: changing permissions of '/var/lib/postgresql/data/pgdata': 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 "chris". This user must also own the server process..
      other combinations of PGDATA and the mountpoint were also not fruitful.

https://stackoverflow.com/a/66502465/5122790:

This answer theoretically works, however I do not want to chmod in between and then change my docker-compose.yml file. There is a comment to this blogpost: https://suedbroecker.net/2020/06/23/run-a-postgressql-container-as-a-non-root-user-in-openshift/, which suggests creating a custom Dockerfile where the correct user and permissions are set, however this didn’t work for me as well (…maybe because my docker-compose.yml was incompatible with that – I tried various combinations of removing/adding some lines with these files:

Dockerfile:

FROM postgres:latest

# see https://stackoverflow.com/a/66502465/5122790

RUN mkdir temp


RUN groupadd non-root-postgres-group
RUN useradd non-root-postgres-user --group non-root-postgres-group

RUN chown -R non-root-postgres-user:non-root-postgres-group /temp
RUN chmod 777 /temp
#RUN chown -R non-root-postgres-user:non-root-postgres-group /usr/local/var/postgres

USER non-root-postgres-user 

docker-compose.yml:

version: "3.8"

#see https://forums.docker.com/t/data-directory-var-lib-postgresql-data-pgdata-has-wrong-ownership/17963/26
services:
  sidb:
    container_name: arg
#    image: postgres:latest
    build: . #see https://stackoverflow.com/a/66502465/5122790
    volumes:
      - ./django_data/db:/tmp/data:rw
      - /etc/passwd:/etc/passwd:ro
    ports:
      - "5433:5432"
    environment:
      - POSTGRES_DB=siddata
      - POSTGRES_USER=siddata
      - POSTGRES_PASSWORD=siddata
      #- PGDATA=/tmp/data #see https://stackoverflow.com/a/61884120/5122790 https://stackoverflow.com/a/66502465/5122790
    #user: 1000:1000

but I didn’t manage to get any of that working.

I found a ton of other answers, but NONE of them provided working code (either a pure docker-command that works on Unix (Ubuntu in my case), or a working docker-compose-file plus dockerfile if needed. There are many smart answers, maybe I’m too stupid to connect the dots, but if somebody could give me a working solution I would be vastly thankful.

Also, as far as I see it, the documentation at https://github.com/docker-library/docs/tree/master/postgres#arbitrary—user-notes even seems to be wrong – their second work-around docker run -it --rm --user "$(id -u):$(id -g)" -v /etc/passwd:/etc/passwd:ro -e POSTGRES_PASSWORD=mysecretpassword postgres does not work on my machine and again gives the error fixing permissions on existing directory /var/lib/postgresql/data ... initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted.

There are also a ton of closed issues (https://github.com/docker-library/postgres/issues/427, https://github.com/docker-library/postgres/issues/476, https://github.com/docker-library/postgres/issues/264, https://github.com/moby/moby/issues/22075, https://github.com/docker-library/postgres/issues/116) and people seem to keep figuring it out, but so far I have not found one solution that works for my demands (docker-compose, no chmoding in between, works on Linux, with a bind-mount, dir not owned by root and not empty).

Source: Docker Questions

Answers

Leave a Reply

Still Have Questions?


Our dedicated development team is here for you!

We can help you find answers to your question for as low as 5$.

Contact Us
faq