diff --git a/README.md b/README.md index ac415e5..f47c24a 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ services: # - POSTGRES_PASSWORD_FILE=/run/secrets/db_password <-- alternative for POSTGRES_PASSWORD (to use with docker secrets) - POSTGRES_EXTRA_OPTS=-Z1 --schema=public --blobs - SCHEDULE=@daily + - BACKUP_ON_START=TRUE - BACKUP_KEEP_DAYS=7 - BACKUP_KEEP_WEEKS=4 - BACKUP_KEEP_MONTHS=6 @@ -75,6 +76,7 @@ Most variables are the same as in the [official postgres image](https://hub.dock |--|--| | BACKUP_DIR | Directory to save the backup at. Defaults to `/backups`. | | BACKUP_SUFFIX | Filename suffix to save the backup. Defaults to `.sql.gz`. | +| BACKUP_ON_START | If set to `TRUE` performs an backup on each container start or restart. Defaults to `FALSE`. | | BACKUP_KEEP_DAYS | Number of daily backups to keep before removal. Defaults to `7`. | | BACKUP_KEEP_WEEKS | Number of weekly backups to keep before removal. Defaults to `4`. | | BACKUP_KEEP_MONTHS | Number of monthly backups to keep before removal. Defaults to `6`. | diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 4d94e79..ff2ecc7 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -1,7 +1,7 @@ ARG BASETAG=alpine FROM postgres:$BASETAG -ARG GOCRONVER=v0.0.10 +ARG GOCRONVER=v0.0.11 ARG TARGETOS ARG TARGETARCH RUN set -x \ @@ -21,6 +21,7 @@ ENV POSTGRES_DB="**None**" \ POSTGRES_EXTRA_OPTS="-Z1" \ POSTGRES_CLUSTER="FALSE" \ SCHEDULE="@daily" \ + BACKUP_ON_START="FALSE" \ BACKUP_DIR="/backups" \ BACKUP_SUFFIX=".sql.gz" \ BACKUP_LATEST_TYPE="symlink" \ @@ -36,12 +37,12 @@ ENV POSTGRES_DB="**None**" \ WEBHOOK_EXTRA_ARGS="" COPY hooks /hooks -COPY backup.sh /backup.sh +COPY backup.sh env.sh init.sh / VOLUME /backups -ENTRYPOINT ["/bin/sh", "-c"] -CMD ["exec /usr/local/bin/go-cron -s \"$SCHEDULE\" -p \"$HEALTHCHECK_PORT\" -- /backup.sh"] +ENTRYPOINT [] +CMD ["/init.sh"] HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f "http://localhost:$HEALTHCHECK_PORT/" || exit 1 diff --git a/backup.sh b/backup.sh index 4a5066a..cbb82dc 100755 --- a/backup.sh +++ b/backup.sh @@ -9,64 +9,7 @@ if [ -d "${HOOKS_DIR}" ]; then trap 'on_error' ERR fi -if [ "${POSTGRES_DB}" = "**None**" -a "${POSTGRES_DB_FILE}" = "**None**" ]; then - echo "You need to set the POSTGRES_DB or POSTGRES_DB_FILE environment variable." - exit 1 -fi - -if [ "${POSTGRES_HOST}" = "**None**" ]; then - if [ -n "${POSTGRES_PORT_5432_TCP_ADDR}" ]; then - POSTGRES_HOST=${POSTGRES_PORT_5432_TCP_ADDR} - POSTGRES_PORT=${POSTGRES_PORT_5432_TCP_PORT} - else - echo "You need to set the POSTGRES_HOST environment variable." - exit 1 - fi -fi - -if [ "${POSTGRES_USER}" = "**None**" -a "${POSTGRES_USER_FILE}" = "**None**" ]; then - echo "You need to set the POSTGRES_USER or POSTGRES_USER_FILE environment variable." - exit 1 -fi - -if [ "${POSTGRES_PASSWORD}" = "**None**" -a "${POSTGRES_PASSWORD_FILE}" = "**None**" -a "${POSTGRES_PASSFILE_STORE}" = "**None**" ]; then - echo "You need to set the POSTGRES_PASSWORD or POSTGRES_PASSWORD_FILE or POSTGRES_PASSFILE_STORE environment variable or link to a container named POSTGRES." - exit 1 -fi - -#Process vars -if [ "${POSTGRES_DB_FILE}" = "**None**" ]; then - POSTGRES_DBS=$(echo "${POSTGRES_DB}" | tr , " ") -elif [ -r "${POSTGRES_DB_FILE}" ]; then - POSTGRES_DBS=$(cat "${POSTGRES_DB_FILE}") -else - echo "Missing POSTGRES_DB_FILE file." - exit 1 -fi -if [ "${POSTGRES_USER_FILE}" = "**None**" ]; then - export PGUSER="${POSTGRES_USER}" -elif [ -r "${POSTGRES_USER_FILE}" ]; then - export PGUSER=$(cat "${POSTGRES_USER_FILE}") -else - echo "Missing POSTGRES_USER_FILE file." - exit 1 -fi -if [ "${POSTGRES_PASSWORD_FILE}" = "**None**" -a "${POSTGRES_PASSFILE_STORE}" = "**None**" ]; then - export PGPASSWORD="${POSTGRES_PASSWORD}" -elif [ -r "${POSTGRES_PASSWORD_FILE}" ]; then - export PGPASSWORD=$(cat "${POSTGRES_PASSWORD_FILE}") -elif [ -r "${POSTGRES_PASSFILE_STORE}" ]; then - export PGPASSFILE="${POSTGRES_PASSFILE_STORE}" -else - echo "Missing POSTGRES_PASSWORD_FILE or POSTGRES_PASSFILE_STORE file." - exit 1 -fi -export PGHOST="${POSTGRES_HOST}" -export PGPORT="${POSTGRES_PORT}" -KEEP_MINS=${BACKUP_KEEP_MINS} -KEEP_DAYS=${BACKUP_KEEP_DAYS} -KEEP_WEEKS=`expr $(((${BACKUP_KEEP_WEEKS} * 7) + 1))` -KEEP_MONTHS=`expr $(((${BACKUP_KEEP_MONTHS} * 31) + 1))` +source "$(dirname "$0")/env.sh" # Pre-backup hook if [ -d "${HOOKS_DIR}" ]; then diff --git a/debian.Dockerfile b/debian.Dockerfile index 5b77f8c..9bb78e4 100644 --- a/debian.Dockerfile +++ b/debian.Dockerfile @@ -1,7 +1,7 @@ ARG BASETAG=latest FROM postgres:$BASETAG -ARG GOCRONVER=v0.0.10 +ARG GOCRONVER=v0.0.11 ARG TARGETOS ARG TARGETARCH @@ -35,6 +35,7 @@ ENV POSTGRES_DB="**None**" \ POSTGRES_EXTRA_OPTS="-Z1" \ POSTGRES_CLUSTER="FALSE" \ SCHEDULE="@daily" \ + BACKUP_ON_START="FALSE" \ BACKUP_DIR="/backups" \ BACKUP_SUFFIX=".sql.gz" \ BACKUP_LATEST_TYPE="symlink" \ @@ -50,12 +51,12 @@ ENV POSTGRES_DB="**None**" \ WEBHOOK_EXTRA_ARGS="" COPY hooks /hooks -COPY backup.sh /backup.sh +COPY backup.sh env.sh init.sh / VOLUME /backups -ENTRYPOINT ["/bin/sh", "-c"] -CMD ["exec /usr/local/bin/go-cron -s \"$SCHEDULE\" -p \"$HEALTHCHECK_PORT\" -- /backup.sh"] +ENTRYPOINT [] +CMD ["/init.sh"] HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f "http://localhost:$HEALTHCHECK_PORT/" || exit 1 diff --git a/docker-bake.hcl b/docker-bake.hcl index 654a3a6..27ff39e 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -15,12 +15,12 @@ variable "BUILD_REVISION" { } target "debian" { - args = {"GOCRONVER" = "v0.0.10"} + args = {"GOCRONVER" = "v0.0.11"} dockerfile = "debian.Dockerfile" } target "alpine" { - args = {"GOCRONVER" = "v0.0.10"} + args = {"GOCRONVER" = "v0.0.11"} dockerfile = "alpine.Dockerfile" } diff --git a/env.sh b/env.sh new file mode 100755 index 0000000..cce7d84 --- /dev/null +++ b/env.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Pre-validate the environment +if [ "${POSTGRES_DB}" = "**None**" -a "${POSTGRES_DB_FILE}" = "**None**" ]; then + echo "You need to set the POSTGRES_DB or POSTGRES_DB_FILE environment variable." + exit 1 +fi + +if [ "${POSTGRES_HOST}" = "**None**" ]; then + if [ -n "${POSTGRES_PORT_5432_TCP_ADDR}" ]; then + POSTGRES_HOST=${POSTGRES_PORT_5432_TCP_ADDR} + POSTGRES_PORT=${POSTGRES_PORT_5432_TCP_PORT} + else + echo "You need to set the POSTGRES_HOST environment variable." + exit 1 + fi +fi + +if [ "${POSTGRES_USER}" = "**None**" -a "${POSTGRES_USER_FILE}" = "**None**" ]; then + echo "You need to set the POSTGRES_USER or POSTGRES_USER_FILE environment variable." + exit 1 +fi + +if [ "${POSTGRES_PASSWORD}" = "**None**" -a "${POSTGRES_PASSWORD_FILE}" = "**None**" -a "${POSTGRES_PASSFILE_STORE}" = "**None**" ]; then + echo "You need to set the POSTGRES_PASSWORD or POSTGRES_PASSWORD_FILE or POSTGRES_PASSFILE_STORE environment variable or link to a container named POSTGRES." + exit 1 +fi + +#Process vars +if [ "${POSTGRES_DB_FILE}" = "**None**" ]; then + POSTGRES_DBS=$(echo "${POSTGRES_DB}" | tr , " ") +elif [ -r "${POSTGRES_DB_FILE}" ]; then + POSTGRES_DBS=$(cat "${POSTGRES_DB_FILE}") +else + echo "Missing POSTGRES_DB_FILE file." + exit 1 +fi +if [ "${POSTGRES_USER_FILE}" = "**None**" ]; then + export PGUSER="${POSTGRES_USER}" +elif [ -r "${POSTGRES_USER_FILE}" ]; then + export PGUSER=$(cat "${POSTGRES_USER_FILE}") +else + echo "Missing POSTGRES_USER_FILE file." + exit 1 +fi +if [ "${POSTGRES_PASSWORD_FILE}" = "**None**" -a "${POSTGRES_PASSFILE_STORE}" = "**None**" ]; then + export PGPASSWORD="${POSTGRES_PASSWORD}" +elif [ -r "${POSTGRES_PASSWORD_FILE}" ]; then + export PGPASSWORD=$(cat "${POSTGRES_PASSWORD_FILE}") +elif [ -r "${POSTGRES_PASSFILE_STORE}" ]; then + export PGPASSFILE="${POSTGRES_PASSFILE_STORE}" +else + echo "Missing POSTGRES_PASSWORD_FILE or POSTGRES_PASSFILE_STORE file." + exit 1 +fi +export PGHOST="${POSTGRES_HOST}" +export PGPORT="${POSTGRES_PORT}" +KEEP_MINS=${BACKUP_KEEP_MINS} +KEEP_DAYS=${BACKUP_KEEP_DAYS} +KEEP_WEEKS=`expr $(((${BACKUP_KEEP_WEEKS} * 7) + 1))` +KEEP_MONTHS=`expr $(((${BACKUP_KEEP_MONTHS} * 31) + 1))` + +# Validate backup dir +if [ '!' -d "${BACKUP_DIR}" -o '!' -w "${BACKUP_DIR}" -o '!' -x "${BACKUP_DIR}" ]; then + echo "BACKUP_DIR points to a file or folder with insufficient permissions." + exit 1 +fi diff --git a/generate-docker-bake.sh b/generate-docker-bake.sh index 6da3c72..15d1ff4 100755 --- a/generate-docker-bake.sh +++ b/generate-docker-bake.sh @@ -2,7 +2,7 @@ set -e -GOCRONVER="v0.0.10" +GOCRONVER="v0.0.11" MAIN_TAG="16" TAGS_EXTRA="15 14 13 12" PLATFORMS="linux/amd64 linux/arm64 linux/arm/v7 linux/s390x linux/ppc64le" diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..0c5428d --- /dev/null +++ b/init.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -Eeo pipefail + +# Prevalidate configuration (don't source) +/env.sh + +EXTRA_ARGS="" +# Initial background backup +if [ "${BACKUP_ON_START}" = "TRUE" ]; then + EXTRA_ARGS="-i" +fi + +exec /usr/local/bin/go-cron -s "$SCHEDULE" -p "$HEALTHCHECK_PORT" $EXTRA_ARGS -- /backup.sh