Bash script for daily backups from PostgreSQL Docker containers

1 week ago 4

I use Docker with Docker Compose for my own apps. I've got a few apps that use PostgreSQL, and a couple of years ago I was looking for a way to backup the databases from those containers in an easy and automated way.

I found a few solutions, but all were way too complicated or inefficient or required more work to restore, or were reliant on the host machine having PostgreSQL installed (which I didn't want because my apps are running different PostgreSQL versions), so I wrote a script myself!

I've been using this bash script to backup the databases from the containers. It's a simple script that runs every day at a specific time (via a simple cron job), and backs up the databases to a specific directory (via pg_dump), without any passwords in the script. It keeps 14 days of backups, compresses them, and cleans up old backups. Oh, and it supports multiple containers!

Here it is:

backup.sh

#!/bin/bash BASE_BACKUP_DIR=/home/www/backups DAYS_TO_KEEP=14 FILE_SUFFIX=_backup.sql declare -A CONTAINERS=( ["amazing-app"]="/home/www/apps/amazing-app" ["another-app"]="/home/www/apps/another-app" ) POSTGRES_USER=postgres POSTGRES_CONTAINER_USER=postgres backup_container() { local container_name=$1 local container_dir=$2 local backup_dir="${BASE_BACKUP_DIR}/${container_name}" local file=$(date +"%Y%m%d%H%M")${FILE_SUFFIX} local output_file="${backup_dir}/${file}" local postgres_container="${container_name}-postgresql-1" local postgres_db="${container_name}" mkdir -p "${backup_dir}" cd "${container_dir}" && docker exec -u ${POSTGRES_CONTAINER_USER} ${postgres_container} pg_dump --dbname="${postgres_db}" --username="${POSTGRES_USER}" > "${output_file}" gzip "${output_file}" echo "${output_file}.gz was created:" ls -l "${output_file}.gz" find "${backup_dir}" -maxdepth 1 -mtime +${DAYS_TO_KEEP} -name "*${FILE_SUFFIX}.gz" -exec rm -f '{}' ';' } for container_name in "${!CONTAINERS[@]}"; do echo "Backing up ${container_name}..." backup_container "${container_name}" "${CONTAINERS[$container_name]}" done echo "Done backing up databases."

Obviously there are some things you can improve, like adding support for multiple databases per container, multiple postgresql container names (per container), and multiple postgresql users. I don't need that, so it'd be unnecessary complexity for me.

I run this with a simple cronjob:

7 3 * * * /home/www/scripts/backup.sh > /home/www/logs/backup.log 2>&1

Which keeps a nice log of the last daily backup in /home/www/logs/backup.log.

I hope this helps you.

Thank you so much for being here. I really appreciate you!

Read Entire Article