How to Store PostgreSQL Data on Host Machine in Docker

In order not to accidentally lose PostgreSQL data, for example, after running the
docker system prune -a --volumes command, they can be stored on the host machine, that is, outside docker.

# docker-compose.yml
version: "3.4"

services:
  database:
    image: postgres:${POSTGRES_VERSION:-14}-alpine
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-app}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
      POSTGRES_USER: ${POSTGRES_USER:-app}
    volumes:
      - ./docker/db/data:/var/lib/postgresql/data:rw
    ports:
      - 5432:5432

In this case, the docker/db/data directory will store the PostgreSQL data corresponding to the
/var/lib/postgresql/data directory in the container.

Let's start the container:

docker-compose up -d

Let's look at the docker/db/data directory:

ls -la docker/db/data
ls: cannot open directory 'docker/db/data': Permission denied

The error occurred because when PostgreSQL starts, it changes the permissions on the
/var/lib/postgresql/data directory, which corresponds to the docker/db/data directory.

ls -la docker/db
drwx------+ 19    70 user 4096 dec 14 13:53 data

The user with id 70 corresponds to the postgres user in the container.

This is not a problem as long as this data is not required for backup or transfer.
It is not recommended to backup PostgreSQL data, for this there are special commands
pg_dumpall -a -U USERNAME > dump.sql to create a data dump and psql -U USERNAME -f dump.sql to restore data.

If PostgreSQL data is needed, then you can run the command to read docker/db/data directory:

sudo setfacl -R -m u:$(id -u):rwX docker/db/data

This command will set the ACL (Access Control List) read / write / execute permissions for the docker/db/data directory for the current user.

ACL is an add-on to the standard system of rights and permissions, that is, if the current user does not have the rights and permissions to read / write / execute a file or directory, then using ACL gives such feature.

If setfacl is not found, then you need to install acl:

apt-get install acl

Now you can see the PostgreSQL data in docker/db/data directory:

ls -la docker/db/data
total 208
drwxrwx---+ 19    70 user  4096 dec 14 13:53 .
drwxrwxr-x+  4 user user  4096 dec 13 18:39 ..
drwxrwx---+  6    70    70  4096 dec 13 19:10 base
drwxrwx---+  2    70    70  4096 dec 14 13:54 global
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_commit_ts
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_dynshmem
-rwxrwx---+  1    70    70  4821 dec 13 16:19 pg_hba.conf
-rwxrwx---+  1    70    70  1636 dec 13 16:19 pg_ident.conf
drwxrwx---+  4    70    70  4096 dec 14 13:58 pg_logical
drwxrwx---+  4    70    70  4096 dec 13 16:19 pg_multixact
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_notify
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_replslot
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_serial
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_snapshots
drwxrwx---+  2    70    70  4096 dec 14 13:53 pg_stat
drwxrwx---+  2    70    70  4096 dec 14 14:07 pg_stat_tmp
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_subtrans
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_tblspc
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_twophase
-rwxrwxr--+  1    70    70     3 dec 13 16:19 PG_VERSION
drwxrwx---+  3    70    70  4096 dec 13 16:19 pg_wal
drwxrwx---+  2    70    70  4096 dec 13 16:19 pg_xact
-rwxrwx---+  1    70    70    88 dec 13 16:19 postgresql.auto.conf
-rwxrwx---+  1    70    70 28718 dec 13 16:19 postgresql.conf
-rwxrwxr--+  1    70    70    24 dec 14 13:53 postmaster.opts
-rwxrwx---+  1    70    70    94 dec 14 13:53 postmaster.pid