mirror of
https://github.com/zulip/docker-zulip.git
synced 2025-10-23 04:51:58 +00:00
postgresql: Add a script to upgrade PostgreSQL data.
This scripts the steps given in the upgrade documentation, altered for supporting Docker managed volumes.
This commit is contained in:
78
README.md
78
README.md
@@ -393,6 +393,13 @@ latest minor release within a major release series.
|
||||
(E.g. authentication settings for `memcached` became mandatory in
|
||||
the `2.1.2` release).
|
||||
|
||||
**Note:** Do not make any changes to the database version or
|
||||
volume. If there is a difference in database version, leave those
|
||||
unchanged for now, and complete that upgrade separately after the
|
||||
Zulip upgrade; see [the section below][pg-upgrade].
|
||||
|
||||
[pg-upgrade]: #upgrading-zulipzulip-postgresql-to-14
|
||||
|
||||
3. Verify that your updated `docker-compose.yml` points to the desired image version,
|
||||
e.g.:
|
||||
```yml
|
||||
@@ -447,68 +454,17 @@ Then stop and restart the container as described in the previous section.
|
||||
|
||||
### Upgrading zulip/zulip-postgresql to 14
|
||||
|
||||
These instructions assume that you have not changed the default
|
||||
Postgres data path (`/opt/docker/zulip/postgresql/data`) in your
|
||||
`docker-compose.yml`. If you have changed it, please replace all
|
||||
occurences of `/opt/docker/zulip/postgresql/data` with your path.
|
||||
The Docker Compose configuration for version 6.0-0 and higher default
|
||||
to using PostgreSQL 14, as the previously-used PostgreSQL 10 is no
|
||||
longer supported. Because the data is specific to the version of
|
||||
PostgreSQL which is running, it must be dumped and re-loaded into a
|
||||
new volume to upgrade. PostgreSQL 14 will refuse to start if provided
|
||||
with un-migrated data from PostgreSQL 10.
|
||||
|
||||
1. Make a backup of your Zulip Postgres data dir.
|
||||
|
||||
2. Stop the Zulip container:
|
||||
|
||||
```
|
||||
docker-compose stop zulip
|
||||
```
|
||||
|
||||
3. Create a new (upgraded) Postgres container using a different data directory:
|
||||
|
||||
```
|
||||
docker run -d \
|
||||
--name postgresnew \
|
||||
-e POSTGRES_DB=zulip \
|
||||
-e POSTGRES_USER=zulip \
|
||||
-e POSTGRES_PASSWORD=zulip \
|
||||
-v /opt/docker/zulip/postgresql/new:/var/lib/postgresql/data:rw \
|
||||
zulip/zulip-postgresql:14
|
||||
```
|
||||
|
||||
4. Use `pg_dumpall` to dump all data from the existing Postgres container to the
|
||||
new Postgres container, and reset the password (for SCRAM-SHA-256 auth upgrade):
|
||||
|
||||
```
|
||||
docker-compose exec database pg_dumpall -U zulip | \
|
||||
docker exec -i postgresnew psql -U zulip
|
||||
|
||||
echo "ALTER USER zulip WITH PASSWORD 'REPLACE_WITH_SECURE_POSTGRES_PASSWORD';" |
|
||||
docker exec -i postgresnew psql -U zulip
|
||||
```
|
||||
|
||||
5. Stop and remove both Postgres containers:
|
||||
|
||||
```
|
||||
docker-compose rm --stop database
|
||||
docker stop postgresnew
|
||||
docker rm postgresnew
|
||||
```
|
||||
|
||||
6. Edit your `docker-compose.yml` to use the `zulip/zulip-postgresql:14` image
|
||||
for the `database` container.
|
||||
|
||||
7. Replace the old Postgres data directory with upgraded data directory:
|
||||
|
||||
```
|
||||
sudo mv /opt/docker/zulip/postgresql/data /opt/docker/zulip/postgresql/old
|
||||
sudo mv /opt/docker/zulip/postgresql/new /opt/docker/zulip/postgresql/data
|
||||
```
|
||||
|
||||
8. Start Zulip up again:
|
||||
|
||||
```
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
That should be it. Your Postgres data has now been updated to use the
|
||||
`zulip/zulip-postgresql` image.
|
||||
The provided `upgrade-postgresql` tool will dump the contents of the
|
||||
`postgresql` image's volume, create a new PostgreSQL 14 volume,
|
||||
perform the necessary migration, update the `docker-compose.yml`
|
||||
file to match, and re-start Zulip.
|
||||
|
||||
### Upgrading from the old galexrt/docker-zulip
|
||||
|
||||
|
103
upgrade-postgresql
Executable file
103
upgrade-postgresql
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eux
|
||||
|
||||
new_version=14
|
||||
|
||||
# Require the `yq` tool
|
||||
if ! command -v yq >/dev/null; then
|
||||
echo "You must install the 'yq' tool to use this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
image=$(yq ".services.database.image" docker-compose.yml)
|
||||
if [[ $image =~ ^zulip/zulip-postgresql:([0-9]+)$ ]]; then
|
||||
old_version="${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "Unexpected PostgreSQL image: $image"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
volume_mount=$(yq ".services.database.volumes.0" docker-compose.yml)
|
||||
if [[ "$volume_mount" =~ ^([^:]+):/var/lib/postgresql/data:rw$ ]]; then
|
||||
old_mountpoint="${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "Unexpected volume mount: $volume_mount"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$new_version" -eq "$old_version" ]; then
|
||||
echo "PostgreSQL image is already version $new_version!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a new volume for the data; scope it with the current
|
||||
# directory, like docker-compose
|
||||
docker_compose_project="$(basename "$(pwd)")"
|
||||
new_volume="postgresql-$new_version"
|
||||
full_new_volume="${docker_compose_project}_${new_volume}"
|
||||
docker volume create "$full_new_volume"
|
||||
trap 'docker volume --force "$full_new_volume"' EXIT
|
||||
|
||||
# Start a new PostgreSQL container of the right version to read in the
|
||||
# dumped database and write a new data dir on the new volume
|
||||
temp_container=$(
|
||||
docker run -d \
|
||||
-e POSTGRES_DB=zulip \
|
||||
-e POSTGRES_USER=zulip \
|
||||
-e POSTGRES_PASSWORD=zulip \
|
||||
-v "$full_new_volume:/var/lib/postgresql/data:rw" \
|
||||
--health-cmd 'psql -U zulip -c "select 1"' \
|
||||
--health-interval 10s \
|
||||
"zulip/zulip-postgresql:$new_version"
|
||||
)
|
||||
trap 'docker volume rm --force "$full_new_volume"; docker rm --force "$temp_container"' EXIT
|
||||
|
||||
# Wait for the new PostgreSQL container to become available
|
||||
tries=0
|
||||
while [ "$(docker inspect --format='{{json .State.Health.Status}}' "$temp_container")" != '"healthy"' ]; do
|
||||
tries=$((tries + 1))
|
||||
if [ "$tries" -gt 5 ]; then
|
||||
echo "PostgreSQL $new_version container failed to start!"
|
||||
exit 1
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
|
||||
# Ensure database is running
|
||||
docker-compose up --wait database
|
||||
|
||||
# Stop the zulip processes which talk to the database
|
||||
zulip_is_running=$(docker-compose ps --filter status=running --services | grep zulip || true)
|
||||
if [ -n "$zulip_is_running" ]; then
|
||||
docker-compose stop zulip
|
||||
fi
|
||||
|
||||
# Transfer the data to the new container
|
||||
docker-compose exec database pg_dumpall -U zulip |
|
||||
docker exec -i "$temp_container" psql -U zulip
|
||||
|
||||
if [ "$old_version" -eq "10" ]; then
|
||||
# Upgrade MD5 password to SCRAM-SHA-256. We escape all 's by doubling them.
|
||||
database_password=$(yq .services.database.environment.POSTGRES_PASSWORD docker-compose.yml |
|
||||
perl -pe "s/'/''/g")
|
||||
echo "ALTER USER zulip WITH PASSWORD '$database_password';" |
|
||||
docker exec -i "$temp_container" psql -U zulip
|
||||
fi
|
||||
|
||||
# Stop the running database
|
||||
docker-compose rm --force --stop database
|
||||
|
||||
# Stop the temporary PostgreSQL container
|
||||
docker stop "$temp_container"
|
||||
docker rm "$temp_container"
|
||||
trap '' EXIT
|
||||
|
||||
# Update the docker-compose.yml file for the new version and data path
|
||||
IMAGE="zulip/zulip-postgresql:$new_version" yq -i '.services.database.image = strenv(IMAGE)' docker-compose.yml
|
||||
VOLUME="$new_volume:/var/lib/postgresql/data:rw" yq -i '.services.database.volumes.0 = strenv(VOLUME)' docker-compose.yml
|
||||
VOLUME="$new_volume" yq -i 'with(.volumes.[strenv(VOLUME)]; . = "" | . tag="!!null")' docker-compose.yml
|
||||
|
||||
# Restart zulip, and the new database container
|
||||
docker-compose up --wait
|
||||
|
||||
echo "Old data from PostgreSQL $old_version is available in $old_mountpoint"
|
Reference in New Issue
Block a user