From f0f0c8b5a25128c7cd1a23dd49f328ab1729bcbd Mon Sep 17 00:00:00 2001 From: Muneer <103816437+dumbstertruck3@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:31:57 +0530 Subject: [PATCH] Add scripts and docs to configure docker backups (#2534) Add scripts and docs to configure docker backups (#2534) --- .env.example | 2 + CONTRIBUTING.md | 6 +- README.md | 1 + docker-compose.yaml | 1 + docs/databases/backup.rst | 121 ++++++++++++++++++++++++++++++++++++++ scripts/backup.sh | 34 +++++++++++ 6 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 docs/databases/backup.rst create mode 100755 scripts/backup.sh diff --git a/.env.example b/.env.example index 057f853951..186c26419e 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,8 @@ POSTGRES_HOST=db POSTGRES_DB=care POSTGRES_PORT=5432 DATABASE_URL=postgres://postgres:postgres@localhost:5433/care +BACKUP_DIR="./care-backups" +DB_BACKUP_RETENTION_PERIOD=7 REDIS_URL=redis://localhost:6380 CELERY_BROKER_URL=redis://localhost:6380/0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e32e20002a..6854688469 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ Any support is welcome. You could help by writing documentation, pull-requests, ### Getting Started -An issue wih the [good first](https://github.com/ohcnetwork/care/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) or [help wanted](https://github.com/ohcnetwork/care/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3A%22help+wanted%22+is%3Aopen) label might be a good place to start with. +An issue with the [good first](https://github.com/ohcnetwork/care/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) or [help wanted](https://github.com/ohcnetwork/care/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3A%22help+wanted%22+is%3Aopen) label might be a good place to start with. ### Setting up the development environment @@ -34,11 +34,13 @@ Make sure you have docker and docker-compose installed. Then run: make build ``` + + #### Using Virtualenv Make sure you have Postgres and Redis installed on your system. -##### Setting up postgtres for the first time +##### Setting up postgres for the first time ```bash sudo -u postgres psql diff --git a/README.md b/README.md index 38d0df9fb0..8aeaf21375 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ make load-dummy-data Prebuilt docker images for server deployments are available on [ghcr](https://github.com/ohcnetwork/care/pkgs/container/care) +For backup and restore use [this](/docs/databases/backup.rst) documentation. ## Contributing We welcome contributions from everyone. Please read our [contributing guidelines](./CONTRIBUTING.md) to get started. diff --git a/docker-compose.yaml b/docker-compose.yaml index b361cbdd8b..25b651fbd6 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,6 +11,7 @@ services: - ./docker/.prebuilt.env volumes: - postgres-data:/var/lib/postgresql/data + - ${BACKUP_DIR:-./care-backups}:/backups ports: - "5433:5432" diff --git a/docs/databases/backup.rst b/docs/databases/backup.rst new file mode 100644 index 0000000000..e0b7018003 --- /dev/null +++ b/docs/databases/backup.rst @@ -0,0 +1,121 @@ +Docker database backup +====================== + +This page explains how to automate the backup process of a Docker database on a daily basis and restore the backup snapshot created by the `backup script <../../scripts/backup.sh>`_. + + Note: This documentation assumes that you are using a Linux-based system. +------------------------------------------------------------------------------- + +Here's how the script works +--------------------------- + +The script automates the process of creating PostgreSQL database backups from a Docker container. It generates a backup file(``.dump``) using the pg_dump utility in PostgreSQL and stores these files in the path configured in ``$BACKUP_DIR`` environment variable which is binded to ``/backups`` in the docker container. Backup files older than ``$DB_BACKUP_RETENTION_PERIOD`` days are deleted when the script is executed by default it is set to 7 days. The backup file is saved with the name ``care_backup_%Y%m%d%H%M%S.sql``. + +Set up a cronjob +---------------- + +Backup your database running on docker automatically everyday by initiating a cronjob. + +Install the package +~~~~~~~~~~~~~~~~~~~ + +For a fedora based system: + +.. code:: bash + + sudo dnf install crond + +For a debian based system: + +.. code:: bash + + sudo apt install cron + +Automate the cronjob +~~~~~~~~~~~~~~~~~~~~ + Note: Make sure you are inside the care directory at the time of executing the following. +------------------------------------------------------------------------------- + +Open up a crontab: + +.. code:: bash + + crontab -e + +Add the cronjob: + +.. code:: bash + + 0 0 * * * "/scripts/backup.sh" + +List the cron jobs +~~~~~~~~~~~~~~~~~~ + +.. code:: bash + + crontab -l + +Check the status of cron +~~~~~~~~~~~~~~~~~~~~~~~~ + +For a fedora based os: + +.. code:: bash + + sudo systemctl status crond + +For a debian based os: + +.. code:: bash + + sudo systemctl status cron + +Verify the cron job +~~~~~~~~~~~~~~~~~ +To verify the cron job is working: + +1. Check the system logs for cron activity, which is usually somewhere in + + .. code:: bash + + /var/log/ + +2. Monitor the backup directory for new files after the scheduled time + +Restoration of the Database +=========================== + +We are basically deleting the container's existing database and creating a new database with the same name. Then we will use ``pg_restore`` to restore the database. Run the following commands in your terminal. + + Make sure you have stopped all the containers except the db before proceeding. And be inside the care directory at the time of executing the following. +------------------------------------------------------------------------------ + +Delete the existing database: + +.. code:: bash + + docker exec -it $(docker ps --format '{{.Names}}' | grep 'care-db') psql -U postgres -c "DROP DATABASE IF EXISTS care;" + +Create the new database: + +.. code:: bash + + docker exec -it $(docker ps --format '{{.Names}}' | grep 'care-db') psql -U postgres -c "CREATE DATABASE care;" + +Execute and copy the name of the file you want to restore the database with: + +.. code:: bash + + sudo ls ./care-backups + +Restore the database: + + Replace with your file name which looks like this ``care_backup_%Y%m%d%H%M%S.sql`` + +.. code:: bash + + docker exec -it $(docker ps --format '{{.Names}}' | grep 'care-db') pg_restore -U postgres -d care /backups/.dump + +------------------------------------------------------------------------------------------------------------------ + + There are way easier ways to do this. If anyone has any particular idea, feel free to make a PR :) diff --git a/scripts/backup.sh b/scripts/backup.sh new file mode 100755 index 0000000000..56efda45c4 --- /dev/null +++ b/scripts/backup.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -ueo pipefail +# Ensure we can find the .env file +ENV_FILE="$(dirname "$(readlink -f "$0")")/../.env" +if [[ ! -f "${ENV_FILE}" ]]; then + echo "Error: .env file not found at ${ENV_FILE}" >&2 + exit 1 +fi +source "${ENV_FILE}" + +container_name="$(docker ps --format '{{.Names}}' | grep 'care-db')" +if [[ -z "${container_name}" ]]; then + echo "Error: PostgreSQL container 'care-db' is not running" >&2 + exit 1 + elif [[ $(echo "${container_name}" | wc -l) -gt 1 ]]; then + echo "Error: Multiple containers matched 'care-db'" >&2 + exit 1 +fi + +date=$(date +%Y%m%d%H%M%S) +#name the file +backup_file="${POSTGRES_DB}_backup_${date}.dump" + +# Remove old backup/backups +docker exec -t ${container_name} find "/backups" -name "${POSTGRES_DB}_backup_*.dump" -type f -mtime +${DB_BACKUP_RETENTION_PERIOD} -exec rm {} \; + +#backup the database +docker exec -t ${container_name} pg_dump -U ${POSTGRES_USER} -Fc -f /backups/${backup_file} ${POSTGRES_DB} + +if ! docker exec -t ${container_name} pg_dump -U ${POSTGRES_USER} -Fc -f /backups/${backup_file} ${POSTGRES_DB}; then + echo "Error: Database backup failed" >&2 + exit 1 +fi +echo "Backup of database '${POSTGRES_DB}' completed and saved as /backups/${backup_file}"