Skip to content

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

@cjpjxjx

Description

@cjpjxjx

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions