Skip to content

Commit

Permalink
Merge pull request #2 from silinternational/develop
Browse files Browse the repository at this point in the history
Release 1.0.0
  • Loading branch information
fillup authored Jan 24, 2019
2 parents 459b9aa + 62d9b5f commit c2fcb4a
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:3.6
FROM alpine:3.8

RUN apk update \
&& apk add --no-cache rsyslog rsyslog-tls \
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ backup: db
docker-compose up -d backup

db:
docker-compose up -d db adminer
docker-compose up -d db

clean:
docker-compose kill
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# postgresql-backup-restore
Service to backup and/or restore PostgreSQL databases using S3
Service to backup and/or restore a PostgreSQL database using S3

## How to use it
1. Create an S3 bucket to hold your backups
Expand All @@ -14,16 +14,20 @@ Service to backup and/or restore PostgreSQL databases using S3

`CRON_SCHEDULE="0 2 * * *"` _defaults to every day at 2:00 AM_ [syntax reference](https://en.wikipedia.org/wiki/Cron)

`DB_NAMES=name1 name2 name3 ...`

`DB_HOST=` hostname of the database server

`DB_USER=` user that accesses the database

`DB_PASSWORD=` password for the `DB_USER`
`DB_NAME=` name of the database

`DB_OPTIONS=opt1 opt2 opt3 ...` optional arguments to supply to the backup or restore commands

`DB_ROOTPASSWORD=` password for the `DB_ROOTUSER`

`DB_ROOTUSER=` database administrative user, typically "postgres" for PostgreSQL databases

`DB_USERPASSWORD=` password for the `DB_USER`

`DB_USER=` user that accesses the database (PostgreSQL "role")

`AWS_ACCESS_KEY=` used for S3 interactions

`AWS_SECRET_KEY=` used for S3 interactions
Expand Down
16 changes: 7 additions & 9 deletions application/backup.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
#!/usr/bin/env sh

for dbName in ${DB_NAMES}; do
logger -p user.info "backing up ${dbName}..."
logger -p user.info "backing up ${DB_NAME}..."

start=$(date +%s)
runny $(PGPASSWORD=${DB_PASSWORD} pg_dump --host=${DB_HOST} --username=${DB_USER} --create --clean ${DB_OPTIONS} --dbname=${dbName} > /tmp/${dbName}.sql)
runny $(PGPASSWORD=${DB_USERPASSWORD} pg_dump --host=${DB_HOST} --username=${DB_USER} --create --clean ${DB_OPTIONS} --dbname=${DB_NAME} > /tmp/${DB_NAME}.sql)
end=$(date +%s)

logger -p user.info "${dbName} backed up ($(stat -c %s /tmp/${dbName}.sql) bytes) in $(expr ${end} - ${start}) seconds."
logger -p user.info "${DB_NAME} backed up ($(stat -c %s /tmp/${DB_NAME}.sql) bytes) in $(expr ${end} - ${start}) seconds."

runny gzip -f /tmp/${dbName}.sql
runny s3cmd put /tmp/${dbName}.sql.gz ${S3_BUCKET}
# runny aws s3 cp /tmp/${dbName}.sql.gz ${S3_BUCKET}
runny gzip -f /tmp/${DB_NAME}.sql
runny s3cmd put /tmp/${DB_NAME}.sql.gz ${S3_BUCKET}
# runny aws s3 cp /tmp/${DB_NAME}.sql.gz ${S3_BUCKET}

logger -p user.info "${dbName} backup stored in ${S3_BUCKET}."
done
logger -p user.info "${DB_NAME} backup stored in ${S3_BUCKET}."
3 changes: 2 additions & 1 deletion application/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env sh

# hostname:port:database:username:password
echo ${DB_HOST}:*:*:${DB_USER}:${DB_PASSWORD} > /root/.pgpass
echo ${DB_HOST}:*:*:${DB_USER}:${DB_USERPASSWORD} > /root/.pgpass
echo ${DB_HOST}:*:*:${DB_ROOTUSER}:${DB_ROOTPASSWORD} >> /root/.pgpass
chmod 600 /root/.pgpass

if [ "${LOGENTRIES_KEY}" ]; then
Expand Down
45 changes: 36 additions & 9 deletions application/restore.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
#!/usr/bin/env sh

for dbName in ${DB_NAMES}; do
logger -p user.info "restoring ${dbName}..."
# Does the database exist?
logger -p user.info "checking for DB ${DB_NAME}..."
result=$(psql --host=${DB_HOST} --username=${DB_ROOTUSER} --list | grep ${DB_NAME})
if [ -z "${result}" ]; then
message="Database "${DB_NAME}" on host "${DB_HOST}" does not exist."
logger -p 1 -t application.crit "${message}"
exit 1
fi

runny s3cmd get -f ${S3_BUCKET}/${dbName}.sql.gz /tmp/${dbName}.sql.gz
runny gunzip -f /tmp/${dbName}.sql.gz
# Ensure the database user exists.
logger -p user.info "checking for DB user ${DB_USER}..."
result=$(psql --host=${DB_HOST} --username=${DB_ROOTUSER} --command='\du' | grep ${DB_USER})
if [ -z "${result}" ]; then
result=$(psql --host=${DB_HOST} --username=${DB_ROOTUSER} --command="create role ${DB_USER} with login password '${DB_USERPASSWORD}' inherit;")
if [ "${result}" != "CREATE ROLE" ]; then
message="Create role command failed: ${result}"
logger -p 1 -t application.crit "${message}"
exit 1
fi
fi

start=$(date +%s)
runny psql --host=${DB_HOST} --username=${DB_USER} ${DB_OPTIONS} < /tmp/${dbName}.sql
end=$(date +%s)
logger -p user.info "changing DB ownership to ${DB_USER}..."
result=$(psql --host=${DB_HOST} --username=${DB_ROOTUSER} --command="alter database ${DB_NAME} owner to ${DB_USER};")
if [ "${result}" != "ALTER DATABASE" ]; then
message="Alter database command failed: ${result}"
logger -p 1 -t application.crit "${message}"
exit 1
fi

logger -p user.info "${dbName} restored in $(expr ${end} - ${start}) seconds."
done
logger -p user.info "restoring ${DB_NAME}..."

runny s3cmd get -f ${S3_BUCKET}/${DB_NAME}.sql.gz /tmp/${DB_NAME}.sql.gz
runny gunzip -f /tmp/${DB_NAME}.sql.gz

start=$(date +%s)
runny psql --host=${DB_HOST} --username=${DB_USER} --dbname=${DB_NAME} ${DB_OPTIONS} < /tmp/${DB_NAME}.sql
end=$(date +%s)

logger -p user.info "${DB_NAME} restored in $(expr ${end} - ${start}) seconds."
26 changes: 16 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ services:
environment:
POSTGRES_PASSWORD: r00tp@ss!

adminer:
image: adminer:4.6.3
ports:
- "8080:8080"
# adminer:
# image: adminer:4.6.3
# ports:
# - "8080:8080"

# DB_HOST - hostname of the database server
# DB_ROOTUSER - administrative user for the database server
# DB_ROOTPASSWORD - password for the DB_ROOTUSER
# DB_USER - user that accesses the database
# DB_PASSWORD - password for the DB_USER
# DB_NAMES - list of databases to back up/restore
# DB_USERPASSWORD - password for the DB_USER
# DB_NAME - name of database to back up/restore
restore:
build: ./
volumes_from:
Expand All @@ -35,9 +37,11 @@ services:
- ./local.env
environment:
DB_HOST: db
DB_ROOTUSER: postgres
DB_ROOTPASSWORD: r00tp@ss!
DB_USER: postgres
DB_PASSWORD: r00tp@ss!
DB_NAMES: world
DB_USERPASSWORD: r00tp@ss!
DB_NAME: world
MODE: restore
CRON_SCHEDULE: "25 * * * *"

Expand All @@ -49,8 +53,10 @@ services:
- ./local.env
environment:
DB_HOST: db
DB_ROOTUSER: postgres
DB_ROOTPASSWORD: r00tp@ss!
DB_USER: postgres
DB_PASSWORD: r00tp@ss!
DB_NAMES: world
DB_USERPASSWORD: r00tp@ss!
DB_NAME: world
MODE: backup
CRON_SCHEDULE: "20 * * * *"

0 comments on commit c2fcb4a

Please sign in to comment.