diff --git a/.dockerignore b/.dockerignore new file mode 120000 index 0000000..3e4e48b --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.gitignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d519e29 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +backups +docker-compose.override.yml diff --git a/.travis.yml b/.travis.yml index 9474ac5..49d060c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,29 @@ -install: - - sudo apt-get install -y linux-image-virtual kernel linux-image-extra-virtual - - curl -sSL https://get.docker.com/ | sudo sh - - sudo pip install docker-compose +sudo: required +services: + - docker + +env: + - COMPOSE_FILE=docker-compose.yml:docker-compose.override.travis.yml script: - ls -lah - - docker-compose up -d dbbackup + - docker-compose up -d --build dbbackup - docker-compose ps - - docker exec dockerpgbackups_dbbackup_1 ls - - docker exec dockerpgbackups_dbbackup_1 date --set="2012-6-29 10:59.59 PM" - - wait 4 - - ls -lah backups/* - - if [[ ! -f "backups/2012/June/foo.dmp" ]]; then exit 1; fi + - docker-compose exec dbbackup /bin/bash -c "until psql -l; do echo 'db unavailable. sleeping'; sleep 1; done" + - docker-compose exec dbbackup ls + # Test backup + - docker-compose exec dbbackup /backups.sh + - export ARCHIVE_DUMP="backups/$(date +%Y)/$(date +%B)/watchkeeper_gis.$(date +%d-%B-%Y).dmp" + - ls -lah ${ARCHIVE_DUMP} + # Test restore + - docker-compose exec dbbackup cp /${ARCHIVE_DUMP} /backups/target_archive.dmp + - docker-compose exec dbbackup psql -l gis + - docker-compose exec dbbackup dropdb gis + - docker-compose exec dbbackup psql -l + - docker-compose exec dbbackup /restore.sh + - docker-compose exec dbbackup psql -l gis + notifications: irc: channels: diff --git a/Dockerfile b/Dockerfile index d4be1e7..347e57b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,12 @@ FROM kartoza/postgis:10.0-2.4 MAINTAINER tim@kartoza.com -RUN apt-get install -y postgresql-client +RUN apt-get -y update; apt-get install -y postgresql-client ADD backups-cron /etc/cron.d/backups-cron RUN touch /var/log/cron.log ADD backups.sh /backups.sh +ADD restore.sh /restore.sh ADD start.sh /start.sh - + +ENTRYPOINT [] CMD ["/start.sh"] diff --git a/README.md b/README.md index 8cffc83..291697e 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ docker run --name="backups"\ In this example I used a volume into which the actual backups will be stored. -# Specifying environment +## Specifying environment You can also use the following environment variables to pass a @@ -74,6 +74,7 @@ user name and password etc for the database connection. * POSTGRES_PORT if not set, defaults to : 5432 * POSTGRES_HOST if not set, defaults to : db * POSTGRES_DBNAME if not set, defaults to : gis +* ARCHIVE_FILENAME you can use your specified filename format here, default to empty, which means it will use default filename format. Example usage: @@ -106,7 +107,7 @@ db: - USERNAME=docker - PASS=docker -dbbackups: +dbbackup: image: kartoza/pg-backup:9.4 hostname: pg-backups volumes: @@ -127,9 +128,51 @@ dbbackups: Then run using: ``` -docker-compose up -d dbbackups +docker-compose up -d dbbackup ``` +## Filename format + +The default backup archive generated will be stored in this directory (inside the container): + +``` +/backups/$(date +%Y)/$(date +%B)/${DUMPPREFIX}_${DB}.$(date +%d-%B-%Y).dmp +``` + +As a concrete example, with `DUMPPREFIX=PG` and if your postgis has DB name `gis`. +The backup archive would be something like: + +``` +/backups/2019/February/PG_gis.13-February-2019.dmp +``` + +If you specify `ARCHIVE_FILENAME` instead (default value is empty). The +filename will be fixed according to this prefix. +Let's assume `ARCHIVE_FILENAME=/backups/latest` +The backup archive would be something like + +``` +/backups/latest.gis.dmp +``` + +## Restoring + +A simple restore script is provided. +You need to specify some environment variables first: + + * TARGET_DB: the db name to restore + * WITH_POSTGIS: Kartoza specific, to generate POSTGIS extension along with the restore process + * TARGET_ARCHIVE: the full path of the archive to restore + + The restore script will delete the `TARGET_DB`, so make sure you know what you are doing. + Then it will create a new one and restore the content from `TARGET_ARCHIVE` + + If you specify these environment variable using docker-compose.yml file, + then you can execute a restore process like this: + + ``` + docker-compose exec dbbackup /restore.sh + ``` ## Credits diff --git a/backups.sh b/backups.sh index dacae16..27bbdcf 100755 --- a/backups.sh +++ b/backups.sh @@ -24,6 +24,10 @@ DBLIST=`psql -l | awk '{print $1}' | grep -v "+" | grep -v "Name" | grep -v "Lis for DB in ${DBLIST} do echo "Backing up $DB" >> /var/log/cron.log - FILENAME=${MYBACKUPDIR}/${DUMPPREFIX}_${DB}.${MYDATE}.dmp + if [ -z "${ARCHIVE_FILENAME:-}" ]; then + FILENAME=${MYBACKUPDIR}/${DUMPPREFIX}_${DB}.${MYDATE}.dmp + else + FILENAME="${ARCHIVE_FILENAME}.${DB}.dmp" + fi pg_dump -Fc -f ${FILENAME} -x -O ${DB} done diff --git a/docker-compose.override.travis.yml b/docker-compose.override.travis.yml new file mode 100644 index 0000000..c98c508 --- /dev/null +++ b/docker-compose.override.travis.yml @@ -0,0 +1,12 @@ +# This is for testing on travis only +# For production we recommend to rather use +# image: kartoza/pg-backup +# in the dbbackup service +dbbackup: + environment: + # Postgres environment variable + # Can be set to execute PG tools directly + - PGHOST=db + - PGUSER=docker + - PGPASSWORD=docker + - PGPORT=5432 diff --git a/docker-compose.yml b/docker-compose.yml index 906c644..ebbaf72 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,13 +5,14 @@ db: image: kartoza/postgis environment: + - ALLOW_IP_RANGE=0.0.0.0/0 - POSTGRES_USER=docker - POSTGRES_PASS=docker dbbackup: build: . volumes: - - ./backup:/backup + - ./backups:/backups environment: - DUMPPREFIX=watchkeeper - POSTGRES_HOST=db @@ -19,5 +20,9 @@ dbbackup: - POSTGRES_USER=docker - POSTGRES_PASS=docker - POSTGRES_PORT=5432 + # For restore script + - TARGET_DB=gis + - WITH_POSTGIS=1 + - TARGET_ARCHIVE=/backups/target_archive.dmp links: - db:db diff --git a/restore.sh b/restore.sh new file mode 100755 index 0000000..14699df --- /dev/null +++ b/restore.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +source /pgenv.sh + +echo "TARGET_DB: ${TARGET_DB}" +echo "WITH_POSTGIS: ${WITH_POSTGIS}" +echo "TARGET_ARCHIVE: ${TARGET_ARCHIVE}" + +if [ -z "${TARGET_ARCHIVE:-}" ] || [ ! -f "${TARGET_ARCHIVE:-}" ]; then + echo "TARGET_ARCHIVE needed." + exit 1 +fi + +if [ -z "${TARGET_DB:-}" ]; then + echo "TARGET_DB needed." + exit 1 +fi + +echo "Dropping target DB" +dropdb ${TARGET_DB} + +if [ -z "${WITH_POSTGIS:-}" ]; then + echo "Recreate target DB without POSTGIS" + createdb -O ${PGUSER} ${TARGET_DB} +else + echo "Recreate target DB with POSTGIS" + createdb -O ${PGUSER} -T template_postgis ${TARGET_DB} +fi + +echo "Restoring dump file" +pg_restore ${TARGET_ARCHIVE} | psql -d ${TARGET_DB} diff --git a/start.sh b/start.sh index c51250d..057052f 100755 --- a/start.sh +++ b/start.sh @@ -45,6 +45,7 @@ export PGPORT=$POSTGRES_PORT export PGHOST=$POSTGRES_HOST export PGDATABASE=$POSTGRES_DBNAME export DUMPPREFIX=$DUMPPREFIX +export ARCHIVE_FILENAME="${ARCHIVE_FILENAME}" " > /pgenv.sh echo "Start script running with these environment options"