Cпособ создания ежедневных бэкапов PostgreSQL из Docker Swarm
15 мая 2021 г.

PostgreSQL Backups

Как делать резервные копии из PostgreSQL, запущенного в Docker Swarm?

Бэкапы PostgreSQL

У запущенного Docker контейнера всегда есть уникальный идентификатор. Docker Swarm (фактически Docker) запускает сервисы с динамическими идентификаторами.

У Docker есть имя службы с фиксированным именем. Мы можем использовать это имя для получения динамического идентификатора службы.

Вы можете просмотреть список всех сервисов с помощью следующей команды

docker service ls

У меня имя сервиса swarm_postgres. Фактически нам нужно получить ID задачи (контейнера), на которой запущен сервис PostgreSQL. Мы можем сделать это с помощью следующей команды:

docker service ps -f "name=swarm_postgres" swarm_postgres -q --no-trunc | head -n1

Эта команда вернет вам идентификатор задачи (контейнера) Docker Swarm из службы postgres. Например: m4q72hmem43talp8ndxn6a37r

Итак, мы знаем идентификатор контейнера и можем сделать резервную копию PostgreSQL, используя pg_dump

docker exec -t swarm_postgres.1.m4q72hmem43talp8ndxn6a37r pg_dump -U dbusername dbname > dump_dbname.sql

В результате этой команды вы получите файл dump_dbname.sql, содержащий дамп SQL.

Все эти действия можно выполнить с помощью одного bash скрипта. Назовем его postgres-backup.sh

#!/bin/bash
#configuration settings
POSTGRES_USER=dbusername
POSTGRES_DB=dbname
CURRENT_MONTH=$(date +%Y-%m)
CURRENT_DATE=$(date +%Y-%m-%d)
CURRENT_DATETIME=$(date +%d-%b-%Y_%H_%M_%Z)
BACKUPS_PATH=/backups
DOCKER_SWARM_SERVICE_NAME=swarm_postgres
####################################
#backup PostgreSQL database
BACKUP_FOLDER=$BACKUPS_PATH/$CURRENT_MONTH/$CURRENT_DATE
if [ ! -d "$BACKUP_FOLDER" ]; then
    mkdir -p "$BACKUP_FOLDER"
fi

echo 'Creating PostgreSQL backups...'
cd "$BACKUP_FOLDER"
if [ -f 'dump_'"$POSTGRES_DB"'.sql' ]; then
   rm 'dump_'"$POSTGRES_DB"'.sql'
fi
db_backup_filename=$POSTGRES_DB'_'$CURRENT_DATETIME'.tar.gz'
postgres_container_id=$(docker service ps -f "name=$DOCKER_SWARM_SERVICE_NAME" $DOCKER_SWARM_SERVICE_NAME -q --no-trunc | head -n1)
docker exec -t symfony-blog_postgres.1."$postgres_container_id" pg_dump -U $POSTGRES_USER $POSTGRES_DB > 'dump_'"$POSTGRES_DB"'.sql'
tar -cf - 'dump_'"$POSTGRES_DB"'.sql' | gzip -9 > "$db_backup_filename"
rm 'dump_'"$POSTGRES_DB"'.sql'

cd "$BACKUP_FOLDER"
md5sum * > MD5SUMS

echo 'Done.'

Есть несколько дополнительных действий. Скрипт создает архив tar.gz, создает файл MD5SUMS, содержащий сумму md5 архива.

Вы можете добавить эту команду в cron и запускать ее каждый день. Просто добавьте строку в /etc/crontab

0 8 * * * root /root/postgres-backup.sh

В этом примере я запускаю этот скрипт каждый день в 8 утра.

Удаление устаревших резервных копий PostgreSQL

Через некоторое время у вас будет много архивов с дампами базы PostgreSQL. Они не нужны все. Я предлагаю хранить резервные копии за последние 14 дней.

Есть способ проверить дату создания файла и удалить устаревшие файлы. Мы можем сделать это с помощью bash скрипта. Назовем его postgres-backups-cleaner.sh

#!/bin/bash
EXPIRE_DAYS=14
SCAN_DIR=/backups
FILES=$(find $SCAN_DIR -type f)
for file in $FILES;
   do
         timestamp=$(date -r $file +%Y%m%d);
         echo "Processing $file file..";
         date1yrs=$(date -d "$timestamp" +%Y);
         date1days=$(date -d "$timestamp" +%j);
         date2yrs=$(date +%Y);
         date2days=$(date +%j);
         diffYear=$(expr "$date2yrs" - "$date1yrs");
         diffYear2days=$(expr "$diffYear" \* 365);
         diffDays=$(expr "$date2days" - "$date1days");
         DAYS=$(expr "$diffYear2days" + "$diffDays");

         if [ "$DAYS" -ge $EXPIRE_DAYS ]
           then
                echo "Deleting $file file...";
                rm "$file";
         fi
   done

Нам нужно запускать этот скрипт ежедневно. Так же, как и с ежедневным бэкапами. Cron - хороший вариант для этого. Отредактируйте файл /etc/crontab и добавьте туда дополнительную строку

0 9 * * * root /root/postgres-backups-cleaner.sh

В этом примере я запускаю этот скрипт каждый день в 9 утра.

Копирование резервных копий в безопасное место

Созданные резервные копии хранятся на хост-машине, на которой запущен Docker Swarm. Будет плохо если что-то случиться с хост-машиной. Можно потерять данные и бэкапы, в том числе.

Я решил копировать бэкапы на домашний компьютер. У меня компьютер работает постоянно. Так что в моем случае это самый дешевый способ хранить бэкапы PostgreSQL. Я добавил cron задачу для копирования бэкапов с хост-машины на мой компьютер с помощью команды rsync

30 21 * * * luxurydab /usr/bin/rsync --progress -zoguhvr --compress-level=9 sshusername@domain.example.com:/backups/ /media/storage/Backups/

Вы можете использовать любое облачное хранилище, такое как Amazon S3, Google Cloud Storage, DigitalOcean Spaces и т. д. Просто добавьте дополнительные действия копирования в bash скрипт создания бекапов.

Последнее обновление 15 мая 2021 г.
Development backup postgresql database