Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to perform an initial backup on startup #158

Merged
merged 5 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`. |
Expand Down
9 changes: 5 additions & 4 deletions alpine.Dockerfile
Original file line number Diff line number Diff line change
@@ -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 \
Expand All @@ -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" \
Expand All @@ -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
59 changes: 1 addition & 58 deletions backup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions debian.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG BASETAG=latest
FROM postgres:$BASETAG

ARG GOCRONVER=v0.0.10
ARG GOCRONVER=v0.0.11
ARG TARGETOS
ARG TARGETARCH

Expand Down Expand Up @@ -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" \
Expand All @@ -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
4 changes: 2 additions & 2 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

Expand Down
66 changes: 66 additions & 0 deletions env.sh
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion generate-docker-bake.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
13 changes: 13 additions & 0 deletions init.sh
Original file line number Diff line number Diff line change
@@ -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
Loading