aboutsummaryrefslogtreecommitdiffstats
path: root/compose/production/postgres
diff options
context:
space:
mode:
Diffstat (limited to 'compose/production/postgres')
-rw-r--r--compose/production/postgres/Dockerfile6
-rw-r--r--compose/production/postgres/maintenance/_sourced/constants.sh5
-rw-r--r--compose/production/postgres/maintenance/_sourced/countdown.sh12
-rw-r--r--compose/production/postgres/maintenance/_sourced/messages.sh41
-rw-r--r--compose/production/postgres/maintenance/_sourced/yes_no.sh16
-rw-r--r--compose/production/postgres/maintenance/backup38
-rw-r--r--compose/production/postgres/maintenance/backups22
-rw-r--r--compose/production/postgres/maintenance/restore55
-rw-r--r--compose/production/postgres/maintenance/rmbackup36
9 files changed, 231 insertions, 0 deletions
diff --git a/compose/production/postgres/Dockerfile b/compose/production/postgres/Dockerfile
new file mode 100644
index 0000000..176a5f1
--- /dev/null
+++ b/compose/production/postgres/Dockerfile
@@ -0,0 +1,6 @@
+FROM docker.io/postgres:16
+
+COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance
+RUN chmod +x /usr/local/bin/maintenance/*
+RUN mv /usr/local/bin/maintenance/* /usr/local/bin \
+ && rmdir /usr/local/bin/maintenance
diff --git a/compose/production/postgres/maintenance/_sourced/constants.sh b/compose/production/postgres/maintenance/_sourced/constants.sh
new file mode 100644
index 0000000..6ca4f0c
--- /dev/null
+++ b/compose/production/postgres/maintenance/_sourced/constants.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+
+BACKUP_DIR_PATH='/backups'
+BACKUP_FILE_PREFIX='backup'
diff --git a/compose/production/postgres/maintenance/_sourced/countdown.sh b/compose/production/postgres/maintenance/_sourced/countdown.sh
new file mode 100644
index 0000000..e6cbfb6
--- /dev/null
+++ b/compose/production/postgres/maintenance/_sourced/countdown.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+
+countdown() {
+ declare desc="A simple countdown. Source: https://superuser.com/a/611582"
+ local seconds="${1}"
+ local d=$(($(date +%s) + "${seconds}"))
+ while [ "$d" -ge `date +%s` ]; do
+ echo -ne "$(date -u --date @$(($d - `date +%s`)) +%H:%M:%S)\r";
+ sleep 0.1
+ done
+}
diff --git a/compose/production/postgres/maintenance/_sourced/messages.sh b/compose/production/postgres/maintenance/_sourced/messages.sh
new file mode 100644
index 0000000..f6be756
--- /dev/null
+++ b/compose/production/postgres/maintenance/_sourced/messages.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+
+
+message_newline() {
+ echo
+}
+
+message_debug()
+{
+ echo -e "DEBUG: ${@}"
+}
+
+message_welcome()
+{
+ echo -e "\e[1m${@}\e[0m"
+}
+
+message_warning()
+{
+ echo -e "\e[33mWARNING\e[0m: ${@}"
+}
+
+message_error()
+{
+ echo -e "\e[31mERROR\e[0m: ${@}"
+}
+
+message_info()
+{
+ echo -e "\e[37mINFO\e[0m: ${@}"
+}
+
+message_suggestion()
+{
+ echo -e "\e[33mSUGGESTION\e[0m: ${@}"
+}
+
+message_success()
+{
+ echo -e "\e[32mSUCCESS\e[0m: ${@}"
+}
diff --git a/compose/production/postgres/maintenance/_sourced/yes_no.sh b/compose/production/postgres/maintenance/_sourced/yes_no.sh
new file mode 100644
index 0000000..fd9cae1
--- /dev/null
+++ b/compose/production/postgres/maintenance/_sourced/yes_no.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+
+yes_no() {
+ declare desc="Prompt for confirmation. \$\"\{1\}\": confirmation message."
+ local arg1="${1}"
+
+ local response=
+ read -r -p "${arg1} (y/[n])? " response
+ if [[ "${response}" =~ ^[Yy]$ ]]
+ then
+ exit 0
+ else
+ exit 1
+ fi
+}
diff --git a/compose/production/postgres/maintenance/backup b/compose/production/postgres/maintenance/backup
new file mode 100644
index 0000000..f72304c
--- /dev/null
+++ b/compose/production/postgres/maintenance/backup
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+
+### Create a database backup.
+###
+### Usage:
+### $ docker compose -f <environment>.yml (exec |run --rm) postgres backup
+
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+
+working_dir="$(dirname ${0})"
+source "${working_dir}/_sourced/constants.sh"
+source "${working_dir}/_sourced/messages.sh"
+
+
+message_welcome "Backing up the '${POSTGRES_DB}' database..."
+
+
+if [[ "${POSTGRES_USER}" == "postgres" ]]; then
+ message_error "Backing up as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again."
+ exit 1
+fi
+
+export PGHOST="${POSTGRES_HOST}"
+export PGPORT="${POSTGRES_PORT}"
+export PGUSER="${POSTGRES_USER}"
+export PGPASSWORD="${POSTGRES_PASSWORD}"
+export PGDATABASE="${POSTGRES_DB}"
+
+backup_filename="${BACKUP_FILE_PREFIX}_$(date +'%Y_%m_%dT%H_%M_%S').sql.gz"
+pg_dump | gzip > "${BACKUP_DIR_PATH}/${backup_filename}"
+
+
+message_success "'${POSTGRES_DB}' database backup '${backup_filename}' has been created and placed in '${BACKUP_DIR_PATH}'."
diff --git a/compose/production/postgres/maintenance/backups b/compose/production/postgres/maintenance/backups
new file mode 100644
index 0000000..a18937d
--- /dev/null
+++ b/compose/production/postgres/maintenance/backups
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+
+### View backups.
+###
+### Usage:
+### $ docker compose -f <environment>.yml (exec |run --rm) postgres backups
+
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+
+working_dir="$(dirname ${0})"
+source "${working_dir}/_sourced/constants.sh"
+source "${working_dir}/_sourced/messages.sh"
+
+
+message_welcome "These are the backups you have got:"
+
+ls -lht "${BACKUP_DIR_PATH}"
diff --git a/compose/production/postgres/maintenance/restore b/compose/production/postgres/maintenance/restore
new file mode 100644
index 0000000..c68f17d
--- /dev/null
+++ b/compose/production/postgres/maintenance/restore
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+
+### Restore database from a backup.
+###
+### Parameters:
+### <1> filename of an existing backup.
+###
+### Usage:
+### $ docker compose -f <environment>.yml (exec |run --rm) postgres restore <1>
+
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+
+working_dir="$(dirname ${0})"
+source "${working_dir}/_sourced/constants.sh"
+source "${working_dir}/_sourced/messages.sh"
+
+
+if [[ -z ${1+x} ]]; then
+ message_error "Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again."
+ exit 1
+fi
+backup_filename="${BACKUP_DIR_PATH}/${1}"
+if [[ ! -f "${backup_filename}" ]]; then
+ message_error "No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again."
+ exit 1
+fi
+
+message_welcome "Restoring the '${POSTGRES_DB}' database from the '${backup_filename}' backup..."
+
+if [[ "${POSTGRES_USER}" == "postgres" ]]; then
+ message_error "Restoring as 'postgres' user is not supported. Assign 'POSTGRES_USER' env with another one and try again."
+ exit 1
+fi
+
+export PGHOST="${POSTGRES_HOST}"
+export PGPORT="${POSTGRES_PORT}"
+export PGUSER="${POSTGRES_USER}"
+export PGPASSWORD="${POSTGRES_PASSWORD}"
+export PGDATABASE="${POSTGRES_DB}"
+
+message_info "Dropping the database..."
+dropdb "${PGDATABASE}"
+
+message_info "Creating a new database..."
+createdb --owner="${POSTGRES_USER}"
+
+message_info "Applying the backup to the new database..."
+gunzip -c "${backup_filename}" | psql "${POSTGRES_DB}"
+
+message_success "The '${POSTGRES_DB}' database has been restored from the '${backup_filename}' backup."
diff --git a/compose/production/postgres/maintenance/rmbackup b/compose/production/postgres/maintenance/rmbackup
new file mode 100644
index 0000000..fdfd20e
--- /dev/null
+++ b/compose/production/postgres/maintenance/rmbackup
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+
+### Remove a database backup.
+###
+### Parameters:
+### <1> filename of a backup to remove.
+###
+### Usage:
+### $ docker-compose -f <environment>.yml (exec |run --rm) postgres rmbackup <1>
+
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+
+working_dir="$(dirname ${0})"
+source "${working_dir}/_sourced/constants.sh"
+source "${working_dir}/_sourced/messages.sh"
+
+
+if [[ -z ${1+x} ]]; then
+ message_error "Backup filename is not specified yet it is a required parameter. Make sure you provide one and try again."
+ exit 1
+fi
+backup_filename="${BACKUP_DIR_PATH}/${1}"
+if [[ ! -f "${backup_filename}" ]]; then
+ message_error "No backup with the specified filename found. Check out the 'backups' maintenance script output to see if there is one and try again."
+ exit 1
+fi
+
+message_welcome "Removing the '${backup_filename}' backup file..."
+
+rm -r "${backup_filename}"
+
+message_success "The '${backup_filename}' database backup has been removed."