kutt icon indicating copy to clipboard operation
kutt copied to clipboard

Postgres 18+ Docker image incompatible with existing ./data/db mount — kutt_postgres becomes unhealthy after image update

Open cjpjxjx opened this issue 1 month ago • 1 comments

After updating the Postgres image (docker compose pull) and restarting, my kutt_postgres container fails healthcheck and refuses to start. The container log indicates the new Postgres 18+ image detects an existing database layout under /var/lib/postgresql/data and refuses to use it without running pg_upgrade or moving data to the new per-major-version layout.

Environment & compose excerpt

  • Host: self-hosted Docker Compose (Debian)
  • Postgres data on host mounted to ./data/db (was historically mounted to /var/lib/postgresql/data)
  • Relevant docker-compose.yml (postgres part):
postgres:
  image: postgres
  volumes:
    - ./data/db:/var/lib/postgresql/data
  environment:
    POSTGRES_DB: ${POSTGRES_DB}
    POSTGRES_PASSWORD: ${DB_PASSWORD}

How to reproduce (what I did)

  1. Running kutt stack with above compose and existing ./data/db worked previously.
  2. Run docker compose pull (Postgres image updated to 18+).
  3. Run docker compose up -d.
  4. kutt_postgres becomes unhealthy and fails to start; other services depend on it and cannot start.

Relevant log output

Error: in 18+, these Docker images are configured to store database data in a
       format which is compatible with "pg_ctlcluster" (specifically, using
       major-version-specific directory names)...
       There appears to be PostgreSQL data in:
         /var/lib/postgresql/data
       This is usually the result of upgrading the Docker image without
       upgrading the underlying database using "pg_upgrade" (which requires both
       versions)...
       The suggested container configuration for 18+ is to place a single mount
       at /var/lib/postgresql which will then place PostgreSQL data in a
       subdirectory...

Root cause (what I determined) The official postgres Docker image changed layout/behavior in Postgres 18+: it uses per-major-version subdirectories under /var/lib/postgresql and expects different mount conventions. If you mount an existing database into /var/lib/postgresql/data and then start a Postgres 18+ image, the image detects the old layout and refuses to start to avoid silently breaking the database — requiring either pg_upgrade or a dump/restore into a freshly initialized data directory.

Impact Users who bind-mount older Postgres data directories (e.g. ./data/db/var/lib/postgresql/data) and then update the image will find their Postgres container does not start; dependent services (like kutt) will fail as well. This is surprising for many users and causes downtime.

Suggested mitigation for kutt docs Please add a short note to the Docker deployment section warning about Postgres 18+ behavior and one of these practical recommendations:

  • Recommend pinning the Postgres image to a known-compatible version (for example postgres:17) in the example docker-compose.yml, or
  • Document the required migration steps briefly (backup with pg_dumpall, create a fresh data mount for the new image, then restore), or
  • Point users to official Postgres Docker guidance about the changed PGDATA layout and pg_upgrade.

A short warning in the README will help many self-hosting users avoid unexpected downtime.

Thanks — happy to provide my compose file and logs if useful.

cjpjxjx avatar Nov 11 '25 09:11 cjpjxjx

English is not my native language and my technical skills are limited; I resolved this issue with the help of ChatGPT, and this issue text was drafted by ChatGPT. I hope this helps others who run into the same problem.

cjpjxjx avatar Nov 11 '25 09:11 cjpjxjx