supabase/postgres

PGDATA forced to default location

Closed this issue · 6 comments

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

The image forces PGDATA to be the default location: /var/lib/postgresql/data and fail it is overriden.
If the user defines PGDATA to another location, it is ignored and the container will fail starting.

Here is an output with PGDATA=/var/lib/postgresql/data/pgdata (NOTE the extra non standard /pgdata at the end):

 2025-05-27 09:00:49.140 UTC [1] FATAL:  "/var/lib/postgresql/data" is not a valid data directory

To Reproduce

You can test using docker and:

docker run --rm -it \
    -e PGDATA=/data \
    -e POSTGRES_PASSWORD=password \
     supabase/postgres:17.4.1.036 

It will fail mentioning:

 2025-05-27 09:25:05.745 UTC [49] FATAL:  data directory "/var/lib/postgresql/data" does not exist

which should not be relevant since we want to use /data.

Expected behavior

The user can point to a custom PGDATA and the container starts.
Using the original postgres image works fine:

docker run --rm -it \
    -e PGDATA=/data \
    -e POSTGRES_PASSWORD=password \
     postgres:latest

System information

  • version: supabase-postgres:17.4.1.036
    but the issue is not specific to this version.
docker run --rm -it \
    -e PGDATA=/data \
    -e POSTGRES_PASSWORD=password \
     supabase/postgres:17.4.1.036 

=> FAIL

docker run --rm -it \
    -e PGDATA=/data \
    -e POSTGRES_PASSWORD=password \
     supabase/postgres:17.4.1.036 postgres   

=> WORKS

Provinding postgres effectively "removes" the surprising default CMD and its "-D", "/etc/postgresql".

Why would /etc/postgresql be passed as data folder ?

Just read through the Dockerfile, so I might be missing something.

All the configs are copied from ansible/files to /etc/postgresql. https://github.com/supabase/postgres/blob/develop/Dockerfile-15#L162

And in this postgresql.conf file which is copied to the image, data_directory is hard coded to /var/lib/postgresql/data.
In the image CMD ["postgres", "-D", "/etc/postgresql"], so even when you specify PGDATA env var postgres is still looking in /var/lib/postgresql/data


docker run --rm -it
-e PGDATA=/data
-e POSTGRES_PASSWORD=password
supabase/postgres:17.4.1.036 postgres
=> WORKS

I'm assuming that when you override the image args, you setup postgres container with default postgres config so it works but you lose the supabase customized config.

The issue I see is that if a user provides PGDATA=/foo/bar it is not expected that postgres uses /etc/postgresql as datadir and I did not spot the reason why it reports missing /var/lib/postgresql/data.

But that's an interesting finding and that means the issue is how the postgres.conf is generated/pathed.

I feel it would make more sense to bring whatever config into the PGDATA specified by the user when the DB is initialized but I am surely missing something.

and I did not spot the reason why it reports missing /var/lib/postgresql/data

Let me clarify.

postgres entrypoint is docker-entrypoint.sh. db directory is created by calling docker_create_db_directories. This function is imported from the upstream postgres repo's docker-entrypoint.sh

If you look at docker_create_db_directories signature, it runs command mkdir -p $PGDATA. This will create directory as specified in PGDATA env. By default, this is /var/lib/postgresql/data. If you override it (e.g., with PGDATA: /data), then only /data will be created.

Now, in supabase postgres repo's Dockerfile the CMD is set to ["postgres", "-D", "/etc/postgresql"].
postgres loads config from /etc/postgresql/postgresql.conf. Inside that file, data_directory is still set to /var/lib/postgresql/data, which hasn’t been created - because PGDATA pointed elsewhere (/data), and that’s the only directory the entrypoint script created. Thus /var/lib/postgresql/data is missing.

The simplest solution is to modify the image’s entrypoint to update the data_directory inside postgresql.conf dynamically

Here is an example. I just used sed to modify the data_directory in postgresql.conf inside container and everything works fine. I had v15 image downloaded on system. Will work the same with v17

services:
  db:
    image: supabase/postgres:15.8.1.060
    ports:
      - 5432:5432
    entrypoint: /bin/bash -c "
        sed -i \"s|data_directory.*|data_directory = '/data'|\" /etc/postgresql/postgresql.conf && \
        exec docker-entrypoint.sh postgres -D /etc/postgresql
     "
    environment:
      POSTGRES_PASSWORD: password
      PGDATA: /data
    volumes:
      - ./data:/data

Closing. PR's welcome if anyone has a proposition for desired changes.