Skip to content

Commit

Permalink
Change: Add upgrade scripts for database files
Browse files Browse the repository at this point in the history
Postgres changes the format of the database files on disk between major
versions. This means that in order to upgrade a postgres database, it is
not sufficient to just bump the container versions.

To help with this process, we now can use migration scripts that will
take care of updating the database version without the need of a manual
dump/restore.

Ref.: DEVOPS-1292
  • Loading branch information
ailox committed Nov 29, 2024
1 parent 9aecf3b commit d03f820
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
28 changes: 27 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,28 @@
ARG POSTGRES_VERSION=16
# This image was forked from the official PostgreSQL image, so it could be
# signed and relied on as an internal dependency.
# The image is modified to include an older version of PostgreSQL, which
# allows us to upgrade the database from the old version to the new one.
ARG POSTGRES_VERSION=17
FROM postgres:${POSTGRES_VERSION}

# we need to redeclare the ARG here, otherwise it will not
# be available in the section below the FROM statement.
ARG POSTGRES_VERSION=17

# Enable and install old version of PostgreSQL.
RUN sed -i 's/$/ 16/' /etc/apt/sources.list.d/pgdg.list
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
postgresql-16 \
; \
rm -rf /var/lib/apt/lists/*

# The old binaries will be in /usr/lib/postgresql/16/bin
ENV PGBINOLD /usr/lib/postgresql/16/bin
ENV PGBINNEW /usr/lib/postgresql/17/bin

ENV PGDATAOLD /var/lib/postgresql/16/data
ENV PGDATANEW /var/lib/postgresql/17/data

COPY bin/upgradeversion /usr/local/bin/
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@

Opensight-Postgres is utilized to provide our Opensight services with the appropriate PostgreSQL container versions.

It is equivalent to the [postgres](https://hub.docker.com/_/postgres) Docker
image. Additionally one previous major version of postgres is added to the
image, so that it can be used to upgrade mounted database files to the
current version.

## Migration process
The opensight-postgres image can be used to migrate older database versions
to the current version used by this image.

If the database is already upgraded, this will be a no-op and the upgrade
process will automatically terminate with exit code 0.

This does not happen automatically however, since it represents a backwards
incompatible change, and has potential to fail. It is therefore recommended
to create backups before attempting a migration.

Usage:

```
docker run -it --rm -v /path/to/database:/var/lib/postgres/data/ opensight-postgres upgradeversion
```

## Maintainer

This project is maintained by [Greenbone AG](https://www.greenbone.net/).
Expand Down
44 changes: 44 additions & 0 deletions bin/upgradeversion
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

set -euo pipefail

# Check postgres version
echo -n "Current database version is "
cat ${PGDATAOLD}/PG_VERSION

# Abort if the old version is not 16
if [ "$(cat ${PGDATAOLD}/PG_VERSION)" != "16" ]; then
echo "Only PostgreSQL 16 is supported for migration with this image."
exit 1
fi

chown -R postgres:postgres "${PGDATAOLD}" "${PGDATANEW}"

# Initialize the new database, if it doesn't exist
if [ ! -s "${PGDATANEW}/PG_VERSION" ]; then
gosu postgres initdb -D ${PGDATANEW}
fi

ls -alh /var/lib/postgresql/17/data/

# mitigate: 'you must have read and write access in the current directory'
cd /var/lib/postgresql

gosu postgres pg_upgrade \
--old-bindir ${PGBINOLD} \
--new-bindir ${PGBINNEW} \
--old-datadir ${PGDATAOLD} \
--new-datadir ${PGDATANEW}

# Check postgres version
echo -n "New migrated database version is "
cat ${PGDATANEW}/PG_VERSION

# if first parameter is 'inplace', we copy the new postgres version to
# the old one. This is not an atomic operation, and therefore risky;
# If the copy operation is not successful, we will end up with a
# corrupted database.
if [ "$1" == "inplace" ]; then
rm -rf ${PGDATAOLD}/*
mv ${PGDATANEW} ${PGDATAOLD}
fi

0 comments on commit d03f820

Please sign in to comment.