diff --git a/optional/postgresql/Dockerfile b/optional/postgresql/Dockerfile index 7a63e6eb..f0e603e9 100644 --- a/optional/postgresql/Dockerfile +++ b/optional/postgresql/Dockerfile @@ -7,14 +7,18 @@ RUN apk add --no-cache \ RUN pip3 install jinja2 # Image specific layers under this line RUN apk add --no-cache \ - postgresql postgresql-libs postgresql-contrib \ + postgresql postgresql-libs postgresql-contrib busybox-suid \ && apk add --virtual .build-deps gcc musl-dev postgresql-dev python3-dev \ && pip3 install psycopg2 anosql \ && apk --purge del .build-deps COPY start.py /start.py +COPY basebackup.sh /basebackup.sh COPY conf /conf +COPY postgres_crontab /etc/postgres_crontab +RUN crontab /etc/postgres_crontab + ENV LANG en_US.UTF-8 RUN mkdir -p /data /backup /run/postgresql \ diff --git a/optional/postgresql/basebackup.sh b/optional/postgresql/basebackup.sh new file mode 100755 index 00000000..04f3d1d0 --- /dev/null +++ b/optional/postgresql/basebackup.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +dest="/backup/base-$(date +%F-%H%M)" +last=$(ls -d /backup/base* | tail -n1) +mkdir $dest || exit $? + +pg_basebackup --pgdata=$dest --format=tar --gzip --username=postgres || exit $? + +# Clean old base backups, keep the last and the current. +for d in /backup/base*; do + if [ "$d" == "$last" ] || [ "$d" == "$dest" ]; then + continue + fi + rm -r $d || exit $? +done + +# Clean the wall archive +cd /backup/wal_archive || exit $? +if [ $(ls *.*.backup | wc -l) -lt 2 ]; then + ls /backup/wal_archive + exit 0 +fi +# Find the single last wal.backup point +prev_wal_start="$(ls *.*.backup | tail -n2 | head -n1)" +for f in $(ls) ; do + if [ "$f" \< "$prev_wal_start" ] || [ "$f" \= "$prev_wal_start" ]; then + rm -v /backup/wal_archive/$f + fi +done +ls /backup/wal_archive diff --git a/optional/postgresql/conf/pg_hba.conf b/optional/postgresql/conf/pg_hba.conf index ca566f1f..f1333b20 100644 --- a/optional/postgresql/conf/pg_hba.conf +++ b/optional/postgresql/conf/pg_hba.conf @@ -85,6 +85,6 @@ host postgres health 127.0.0.1/32 md5 host all all ::1/128 reject # Allow replication connections from localhost, by a user with the # replication privilege. -local replication all reject +local replication all peer map=local host replication all 127.0.0.1/32 reject host replication all ::1/128 reject diff --git a/optional/postgresql/postgres_crontab b/optional/postgresql/postgres_crontab new file mode 100644 index 00000000..2d45c5a2 --- /dev/null +++ b/optional/postgresql/postgres_crontab @@ -0,0 +1 @@ +11 4 * * * /basebackup.sh > /proc/1/fd/1 2>/proc/1/fd/2 diff --git a/optional/postgresql/start.py b/optional/postgresql/start.py index 59d89044..65f0a57c 100755 --- a/optional/postgresql/start.py +++ b/optional/postgresql/start.py @@ -5,6 +5,7 @@ import psycopg2 import jinja2 import glob import os +import subprocess def setup(): conn = psycopg2.connect(user = 'postgres') @@ -32,7 +33,6 @@ if not os.path.exists('/data/pg_wal'): os.system("su - postgres -c 'initdb -D /data'") # Create backup directory structure, if it does not yet exist -os.system("mkdir -p /backup/dump") os.system("mkdir -p /backup/wal_archive") os.system("chown -R postgres:postgres /backup") @@ -46,5 +46,9 @@ os.system("su - postgres -c 'pg_ctl start -D /data -o \"-h localhost\"'") setup() os.system("su - postgres -c 'pg_ctl stop -m smart -w -D /data'") +out=open("/proc/1/fd/1", "w") +err=open("/proc/1/fd/2", "w") +# Run the cron deamon +subprocess.Popen(["crond", "-f", "-d7"], stdout=out, stderr=err) # Run postgresql service os.system("su - postgres -c 'postgres -D /data -h \*'")