Search code examples
postgresqldockerubuntudocker-composefile-permissions

Permission issue with PostgreSQL in docker container


I'm trying to run a docker image with PostgreSQL that has a volume configured for persisting data.

docker-compose.yml

version: '3.1'

services:
  db:
    image: postgres
    restart: always
    volumes:
      - ./data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example

When I start the container I see the output

fixing permissions on existing directory /var/lib/postgresql/data ... ok

and the data folder is no longer readable for me.

If I elevate myself and access the data directory I can see that the files are there. Furthermore, the command ls -ld data gives me

drwx------ 19 systemd-coredump root 4096 May 17 16:22 data

I can manually set the directory permission with sudo chmod 755 data, but that only works until I restart the container.

Why does this happen, and how can I fix it?


Solution

  • The other answer indeed points to the root cause of the problem, however the help page it points to does not contain a solution. Here is what I came up with to make this work for me:

    1. start the container using your normal docker-compose file, this creates the directory with the hardcoded uid:gid (999:999)
    version: '3.7'
    
    services:
      db:
        image: postgres
        container_name: postgres
        volumes:
          - ./data:/var/lib/postgresql/data
        environment:
          POSTGRES_USER: fake_database_user
          POSTGRES_PASSWORD: fake_database_PASSWORD
    
    1. stop the container and manually change the ownership to uid:gid you want (I'll use 1000:1000 for this example
    $ docker stop postgres
    $ sudo chown -R 1000:1000 ./data 
    
    1. Edit your docker file to add your desired uid:gid and start it up again using docker-compose (notice the user:)
    version: '3.7'
    
    services:
      db:
        image: postgres
        container_name: postgres
        volumes:
          - ./data:/var/lib/postgresql/data
        user: 1000:1000
        environment:
          POSTGRES_USER: fake_database_user
          POSTGRES_PASSWORD: fake_database_password
    

    The reason you can't just use user: from the start is that if the image runs as a different user it fails to create the data files.

    On the image documentation page, it does mention a solution to add a volume to expose the /etc/passwd file as read-only in the image when providing --user option, however, that did not work for me with the latest image, as I was getting the following error. In fact none of the three proposed solutions worked for me.

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