diff --git a/README.md b/README.md index 8fef138..9db7998 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,8 @@ Several ENVs and 'up' commands were added to faciliate running different distrib | name | purpose | default| | ---- | ---- | ----- | | COMPOSE_IMAGE | 'image:' for docker-compose service | labkey/community | -| IDENT | isolate postgres data directory from other containers (.pgdata/[IDENT]-data) | postgres | +| IDENT | isolate postgres data directory from other containers (./pgdata/[IDENT]-[PG_VERSION]-data) | postgres | +| PG_VERSION | Postgres major version (image tag) and data-dir suffix; see _Postgres version & upgrading_ below | 18 | These can be leveraged with commands such as: * COMPOSE_IMAGE=labkey/lims_starter IDENT=lims_starter LABKEY_DISTRIBUTION=lims_starter make up-lims_starter @@ -227,6 +228,36 @@ The `POSTGRES_*` default values are meant to match those of the [library/postgre | POSTGRES_PORT | port of database; compounds to URI connection string | `5432` | | POSTGRES_USER | user of database which container will utilize as main dataSource | `postgres` | +### Postgres version & upgrading + +The docker-compose dev database defaults to **Postgres 18** (`image: postgres:${PG_VERSION:-18}`). +The major version is also baked into the data-directory name (`./pgdata/postgres--data`, +or `./pgdata/--data` for the enterprise/lims_starter/allpg services), so each +major version gets its own on-disk directory and switching versions never corrupts an existing one. + +Postgres does **not** read a data directory created by an older major version, so an existing pg15 +dev database cannot be started by the pg18 image in place. You have two options: + +* **Start fresh on pg18 (simplest for dev):** just `make up`. A new, empty `postgres-18-data` + directory is created and your old pg15 data is left untouched at `./pgdata/postgres-data` + (you can delete that directory once you no longer need it). +* **Keep running your existing pg15 data:** pin the old version — `PG_VERSION=15 make up`. Note this + reads `./pgdata/postgres-15-data`; if your data predates this change it lives in the legacy + `./pgdata/postgres-data` directory — rename it to `postgres-15-data` first, or dump/restore it. + +To migrate real data from pg15 to pg18, dump from a running pg15 container and restore into pg18: + +```bash +PG_VERSION=15 docker compose up -d pg-community +docker compose exec pg-community pg_dumpall -U postgres > dump.sql +PG_VERSION=15 docker compose down +docker compose up -d pg-community # pg18, fresh data dir +cat dump.sql | docker compose exec -T pg-community psql -U postgres +``` + +> The pg service no longer silences its output, so version/startup errors appear in +> `docker compose logs pg-community` instead of the container silently crash-looping. + ## SMTP These replace values previously housed in `context.xml` (`ROOT.xml` or `labkey.xml`) governing `mail/Session` resources. diff --git a/docker-compose.yml b/docker-compose.yml index f40a403..e4d207a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -97,20 +97,26 @@ services: - SLEEP=${SLEEP:-0} pg-community: - image: postgres:15 + image: postgres:${PG_VERSION:-18} # deploy: # resources: # limits: # cpus: '0.25' # memory: 512M - # silent postgres w/o needing to remake the container! + # run postgres through the image entrypoint; logs stay visible so + # version/startup errors (e.g. pg data-dir incompatibility) surface in + # `docker compose logs` instead of the container silently crash-looping. entrypoint: - "/bin/bash" - "-c" - - "docker-entrypoint.sh postgres >/dev/null 2>&1" + - "docker-entrypoint.sh postgres" environment: - POSTGRES_USER=${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-localdevpassword} + # pin PGDATA to the pre-18 default so the bind mount below keeps + # persisting data: the postgres:18 image moved its default PGDATA to + # /var/lib/postgresql/18/docker, which would bypass this mount entirely. + - PGDATA=/var/lib/postgresql/data healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 30s @@ -118,7 +124,7 @@ services: retries: 3 start_period: 40s volumes: - - ./pgdata/postgres-data:/var/lib/postgresql/data + - ./pgdata/postgres-${PG_VERSION:-18}-data:/var/lib/postgresql/data ports: - ${PG_PORT:-54321}:5432 @@ -220,20 +226,26 @@ services: - SLEEP=${SLEEP:-0} pg-allpg: - image: postgres:15 + image: postgres:${PG_VERSION:-18} # deploy: # resources: # limits: # cpus: '0.25' # memory: 512M - # silent postgres w/o needing to remake the container! + # run postgres through the image entrypoint; logs stay visible so + # version/startup errors (e.g. pg data-dir incompatibility) surface in + # `docker compose logs` instead of the container silently crash-looping. entrypoint: - "/bin/bash" - "-c" - - "docker-entrypoint.sh postgres >/dev/null 2>&1" + - "docker-entrypoint.sh postgres" environment: - POSTGRES_USER=${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-localdevpassword} + # pin PGDATA to the pre-18 default so the bind mount below keeps + # persisting data: the postgres:18 image moved its default PGDATA to + # /var/lib/postgresql/18/docker, which would bypass this mount entirely. + - PGDATA=/var/lib/postgresql/data healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 30s @@ -241,7 +253,7 @@ services: retries: 3 start_period: 40s volumes: - - ./pgdata/${IDENT:-postgres}-data:/var/lib/postgresql/data + - ./pgdata/${IDENT:-postgres}-${PG_VERSION:-18}-data:/var/lib/postgresql/data ports: - ${PG_PORT:-54321}:5432 @@ -341,20 +353,26 @@ services: - SLEEP=${SLEEP:-0} pg-enterprise: - image: postgres:15 + image: postgres:${PG_VERSION:-18} # deploy: # resources: # limits: # cpus: '0.25' # memory: 512M - # silent postgres w/o needing to remake the container! + # run postgres through the image entrypoint; logs stay visible so + # version/startup errors (e.g. pg data-dir incompatibility) surface in + # `docker compose logs` instead of the container silently crash-looping. entrypoint: - "/bin/bash" - "-c" - - "docker-entrypoint.sh postgres >/dev/null 2>&1" + - "docker-entrypoint.sh postgres" environment: - POSTGRES_USER=${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-localdevpassword} + # pin PGDATA to the pre-18 default so the bind mount below keeps + # persisting data: the postgres:18 image moved its default PGDATA to + # /var/lib/postgresql/18/docker, which would bypass this mount entirely. + - PGDATA=/var/lib/postgresql/data healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 30s @@ -362,7 +380,7 @@ services: retries: 3 start_period: 40s volumes: - - ./pgdata/${IDENT:-postgres}-data:/var/lib/postgresql/data + - ./pgdata/${IDENT:-postgres}-${PG_VERSION:-18}-data:/var/lib/postgresql/data ports: - ${PG_PORT:-54321}:5432 @@ -466,20 +484,26 @@ services: - LABKEY_EXTERNAL_MODULES=${LABKEY_EXTERNAL_MODULES:-/labkey/files/externalModules} pg-lims_starter: - image: postgres:15 + image: postgres:${PG_VERSION:-18} # deploy: # resources: # limits: # cpus: '0.25' # memory: 512M - # silent postgres w/o needing to remake the container! + # run postgres through the image entrypoint; logs stay visible so + # version/startup errors (e.g. pg data-dir incompatibility) surface in + # `docker compose logs` instead of the container silently crash-looping. entrypoint: - "/bin/bash" - "-c" - - "docker-entrypoint.sh postgres >/dev/null 2>&1" + - "docker-entrypoint.sh postgres" environment: - POSTGRES_USER=${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-localdevpassword} + # pin PGDATA to the pre-18 default so the bind mount below keeps + # persisting data: the postgres:18 image moved its default PGDATA to + # /var/lib/postgresql/18/docker, which would bypass this mount entirely. + - PGDATA=/var/lib/postgresql/data healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 30s @@ -487,7 +511,7 @@ services: retries: 3 start_period: 40s volumes: - - ./pgdata/${IDENT:-postgres}-data:/var/lib/postgresql/data + - ./pgdata/${IDENT:-postgres}-${PG_VERSION:-18}-data:/var/lib/postgresql/data ports: - ${PG_PORT:-54321}:5432