Browse Source

implement backup/restore

main
Nicolas Massé 5 days ago
parent
commit
a58726ba05
  1. 22
      postgresql/config/backup.sh
  2. 1
      postgresql/config/config.env
  3. 37
      postgresql/config/init.sh
  4. 4
      postgresql/postgresql-backup.container
  5. 6
      postgresql/postgresql-init.container
  6. 3
      postgresql/postgresql-server.container
  7. 3
      postgresql/postgresql-upgrade.container
  8. 17
      postgresql/postgresql.pod
  9. 4
      postgresql/postgresql.target

22
postgresql/config/backup.sh

@ -3,9 +3,12 @@ set -Eeuo pipefail
export PGHOST=/var/run/postgresql
BACKUP_DIR=/backup/$(date +%Y%m%d)
BACKUP_DIR=/var/lib/postgresql/backup/$(date +%Y-%m-%d_%H-%M-%S)/
mkdir -p "$BACKUP_DIR"
echo "Starting complete backup of the whole PostgreSQL server..."
pg_basebackup --pgdata=$BACKUP_DIR --format=tar --manifest-checksums=SHA256 --verbose
echo "Starting backup of individual databases..."
psql -c "SELECT datname FROM pg_database WHERE datname NOT IN ('template0', 'template1', 'postgres');" -t | while read db; do
if [ -z "$db" ]; then
continue
@ -14,6 +17,17 @@ psql -c "SELECT datname FROM pg_database WHERE datname NOT IN ('template0', 'tem
echo "Backup of database $db..."
pg_dump -c --if-exists "$db" | gzip -c > "$BACKUP_DIR/dump-$db.sql.gz"
done
echo "Complete backup of the whole PostgreSQL server..."
pg_basebackup -D "$BACKUP_DIR/pg_basebackup"
echo "Backups stored in $BACKUP_DIR"
echo "Backup stored in $BACKUP_DIR."
# backup rotation / retention policy
POSTGRES_BACKUP_RETENTION=${POSTGRES_BACKUP_RETENTION:-7}
if [[ "$POSTGRES_BACKUP_RETENTION" -gt 0 ]] && ls -1ct /var/lib/postgresql/backup/*/backup_manifest &>/dev/null; then
echo "Applying backup retention policy: keeping the last $POSTGRES_BACKUP_RETENTION backups."
ls -1ct /var/lib/postgresql/backup/*/backup_manifest | tail -n "+$((POSTGRES_BACKUP_RETENTION + 1))" | while read old_backup; do
old_backup=$(dirname "$old_backup")
echo "Removing old backup: $old_backup"
rm -rf "$old_backup"
done
else
echo "No backup retention policy applied."
fi

1
postgresql/config/config.env

@ -5,3 +5,4 @@ POSTGRES_HOST_AUTH_METHOD=scram-sha-256
POSTGRES_INITDB_ARGS=--auth-host=scram-sha-256
PGPORT=5432
PG_MAJOR=17
POSTGRES_BACKUP_RETENTION=7

37
postgresql/config/init.sh

@ -0,0 +1,37 @@
#!/bin/bash
set -Eeuo pipefail
last_backup=""
for f in /var/lib/postgresql/backup/*/backup_manifest; do
# If there are no backups, the glob pattern above won't match any files
if [ ! -f "$f" ]; then
continue
fi
# Check if this is the most recent backup
if [ -z "$last_backup" ] || [ "$f" -nt "$last_backup" ]; then
last_backup="$f"
fi
done
if [ -n "$last_backup" ]; then
last_backup=$(dirname "$last_backup")
echo "Restoring from last backup: $last_backup..."
mkdir -p "$PGDATA"
tar -xvf "$last_backup/base.tar" -C "$PGDATA"
if [ -f "$last_backup/pg_wal.tar" ]; then
mkdir -p "$PGDATA/pg_wal"
tar -xvf "$last_backup/pg_wal.tar" -C "$PGDATA/pg_wal"
fi
echo "Verifying backup integrity..."
pg_verifybackup -m "$last_backup/backup_manifest" "$PGDATA"
echo "Setting ownership and permissions..."
chown -R postgres:postgres "$PGDATA"
chmod 700 "$PGDATA"
echo "Restoration complete."
exit 0
fi
echo "No previous backup found, initializing an empty database!"
exec /usr/local/bin/docker-ensure-initdb.sh

4
postgresql/postgresql-backup.container

@ -25,12 +25,8 @@ User=postgres
Volume=/var/lib/quadlets/postgresql:/var/lib/postgresql:z
Volume=/etc/quadlets/postgresql/backup.sh:/usr/local/bin/backup.sh:z,ro
# This container is part of a Pod
Pod=postgresql.pod
# Share /var/run/postgresql/ between containers in the pod for the Unix socket
Volume=/var/run/quadlets/postgresql:/var/run/postgresql:z
Volume=/var/lib/quadlets/postgresql/backup:/backup:z
[Service]
Restart=no

6
postgresql/postgresql-init.container

@ -27,13 +27,11 @@ Environment=PGDATA=/var/lib/postgresql/${PG_MAJOR}/docker
EnvironmentFile=/etc/quadlets/postgresql/config.env
# Use the official entrypoint script to initialize the database
Entrypoint=/usr/local/bin/docker-ensure-initdb.sh
Entrypoint=/usr/local/bin/init.sh
# Volume mounts
Volume=/var/lib/quadlets/postgresql:/var/lib/postgresql:z
# This container is part of a Pod
Pod=postgresql.pod
Volume=/etc/quadlets/postgresql/init.sh:/usr/local/bin/init.sh:z,ro
[Service]
Restart=no

3
postgresql/postgresql-server.container

@ -41,9 +41,6 @@ HealthTimeout=10s
HealthStartPeriod=60s
HealthRetries=3
# This container is part of a Pod
Pod=postgresql.pod
# Share /var/run/postgresql/ between containers in the pod for the Unix socket
Volume=/var/run/quadlets/postgresql:/var/run/postgresql:z

3
postgresql/postgresql-upgrade.container

@ -32,9 +32,6 @@ EnvironmentFile=/etc/quadlets/postgresql/config.env
# Volume mounts
Volume=/var/lib/quadlets/postgresql:/var/lib/postgresql:z
# This container is part of a Pod
Pod=postgresql.pod
[Service]
Restart=no
TimeoutStartSec=600

17
postgresql/postgresql.pod

@ -1,17 +0,0 @@
[Unit]
Description=PostgreSQL Database Server - Pod
Documentation=https://hub.docker.com/_/postgres/
After=network.target
Before=postgresql.target
# Only start if PostgreSQL has been configured
ConditionPathExists=/etc/quadlets/postgresql/config.env
# Start/stop this unit when the target is started/stopped
PartOf=postgresql.target
[Pod]
PodName=postgresql
[Install]
WantedBy=postgresql.target

4
postgresql/postgresql.target

@ -1,8 +1,8 @@
[Unit]
Description=PostgreSQL Service Target
Documentation=man:systemd.target(5)
Requires=postgresql-pod.service postgresql-server.service postgresql-upgrade.service postgresql-init.service postgresql-set-major.service
After=postgresql-pod.service postgresql-server.service postgresql-upgrade.service postgresql-init.service postgresql-set-major.service
Requires=postgresql-server.service postgresql-upgrade.service postgresql-init.service postgresql-set-major.service
After=postgresql-server.service postgresql-upgrade.service postgresql-init.service postgresql-set-major.service
# Allow isolation - can stop/start this target independently
AllowIsolate=yes

Loading…
Cancel
Save