Бэкапы при локальной разработке — полное руководство для разработчика

Бэкапы при локальной разработке: почему разработчики теряют данные и как этого избежать

Большинство разработчиков делают бэкапы продакшена и игнорируют локальную среду — до первого момента, когда случайная команда удаляет три часа ручной настройки тестовых данных. Короткий ответ на вопрос «надо ли бэкапить локальную базу»: да, и это занимает одну минуту настройки.


Почему локальные данные важнее, чем кажется

Продакшен обычно защищён: облачные провайдеры делают автоматические снапшоты, есть мониторинг, алерты. Локальная среда разработчика — это дикий запад.

Типичные сценарии потери данных на локальной машине:

  • Запущена миграция с ошибкой — данные в нескольких таблицах стёрты
  • AI-агент (Cursor, GitHub Copilot Workspace, Claude) выполнил деструктивный SQL-запрос
  • docker-compose down -v — удалены все volumes вместе с данными
  • Случайное rm -rf в директории проекта
  • Переустановка ОС без сохранения данных Docker
  • Откат ветки в Git без понимания, что миграции уже применились к базе

Каждый из этих сценариев превращает час работы в потерянное время. Бэкап — это страховка с минимальной стоимостью.


Что именно нужно бэкапить при разработке

Разграничим понятия:

  • Схема базы данных (таблицы, индексы, триггеры) — обычно уже версионирована через миграции (Alembic, Flyway, Prisma Migrate, Django migrations). Её бэкапить в виде файла необязательно — достаточно git-репозитория.
  • Данные (строки в таблицах) — вот что действительно теряется и что нужно бэкапить.
  • Seed-данные — отдельная тема (см. ниже).

Бэкап SQLite при локальной разработке

SQLite — это один файл на диске. Его легко скопировать, но есть нюанс: копирование во время активной записи может привести к повреждению копии. Всегда используйте встроенную команду .backup.

Правильный способ

sqlite3 my_database.db ".backup 'backup_$(date +%Y%m%d_%H%M%S).db'"

Эта команда создаёт консистентный снапшот даже при открытом соединении с базой. Никаких блокировок, никакого повреждения данных.

Восстановление

cp backup_20260501_143000.db my_database.db

Или через sqlite3:

sqlite3 my_database.db ".restore 'backup_20260501_143000.db'"

Автоматизация через npm-скрипты

Если вы работаете на Node.js-проекте, добавьте в package.json:

{
  "scripts": {
    "db:backup": "sqlite3 app.db \".backup 'backups/backup_$(date +%Y%m%d_%H%M%S).db'\"",
    "db:restore": "echo 'Usage: cp backups/BACKUP_FILE.db app.db'"
  }
}

Теперь перед любой рискованной операцией: npm run db:backup.

Автоматизация через Makefile

DB_FILE=app.db
BACKUP_DIR=backups

db-backup:
	@mkdir -p $(BACKUP_DIR)
	sqlite3 $(DB_FILE) ".backup '$(BACKUP_DIR)/backup_$(shell date +%Y%m%d_%H%M%S).db'"
	@echo "Бэкап создан"

db-restore:
	@echo "Доступные бэкапы:"
	@ls -la $(BACKUP_DIR)

Бэкап PostgreSQL при локальной разработке

Базовый дамп

pg_dump -h localhost -U postgres -Fc mydb > backups/backup_$(date +%Y%m%d_%H%M%S).dump

Флаг -Fc создаёт сжатый бинарный дамп, который позволяет восстанавливать таблицы выборочно. Для SQL-формата (человекочитаемый):

pg_dump -h localhost -U postgres --format=plain mydb > backup.sql

Восстановление

# Для -Fc формата
pg_restore -h localhost -U postgres -d mydb_restored backup.dump

# Для SQL-формата
psql -h localhost -U postgres -d mydb_restored < backup.sql

Пропуск пароля через .pgpass

Создайте файл ~/.pgpass (Linux/macOS) или %APPDATA%\postgresql\pgpass.conf (Windows):

localhost:5432:mydb:postgres:yourpassword

Установите права: chmod 600 ~/.pgpass. Теперь pg_dump не будет спрашивать пароль.

Только данные без схемы

pg_dump -h localhost -U postgres --data-only -Fc mydb > data_only_backup.dump

Полезно при разработке: схема уже в миграциях, нужны только данные.

Конкретная таблица

pg_dump -h localhost -U postgres -t users -t orders -Fc mydb > selected_tables.dump

Бэкап MySQL и MariaDB при локальной разработке

mysqldump -u root -p --single-transaction mydb > backup_$(date +%Y%m%d_%H%M%S).sql

Флаг --single-transaction обеспечивает консистентность без блокировки таблиц (работает для InnoDB).

Восстановление:

mysql -u root -p mydb < backup.sql

Бэкап MongoDB при локальной разработке

mongodump --uri="mongodb://localhost:27017/mydb" --out=backups/$(date +%Y%m%d_%H%M%S)

Восстановление:

mongorestore --uri="mongodb://localhost:27017/mydb" backups/20260501_143000/mydb/

Docker и базы данных: самые частые ошибки

Ошибка №1: данные внутри контейнера

# ПЛОХО — данные исчезнут при docker-compose down -v
services:
  db:
    image: postgres:16
# ХОРОШО — данные хранятся на хосте
services:
  db:
    image: postgres:16
    volumes:
      - ./pgdata:/var/lib/postgresql/data

Теперь папка ./pgdata в вашем проекте содержит все данные PostgreSQL. Добавьте её в .gitignore.

Бэкап данных из Docker-контейнера

# PostgreSQL в Docker
docker exec -t my_postgres_container pg_dump -U postgres mydb > backup.sql

# SQLite в Docker
docker cp my_container:/app/database.db ./backups/backup_$(date +%Y%m%d_%H%M%S).db

Восстановление в Docker

cat backup.sql | docker exec -i my_postgres_container psql -U postgres mydb

Seed-данные vs бэкап: в чём разница и что важнее

Многие разработчики делают бэкап вместо того, чтобы написать seed-скрипты. Разберём разницу:

| Критерий | Бэкап | Seed-скрипты | |---|---|---| | Совместимость со схемой | Может конфликтовать после миграций | Всегда актуальны (пишутся вместе с миграциями) | | Передача коллеге | Сложно (нужна одинаковая версия схемы) | Легко (просто запустить скрипт) | | Воспроизводимость | Нет (зависит от момента создания) | Да (одинаковый результат всегда) | | Размер | Может быть большим | Маленький, в коде | | Использование | Экстренное восстановление | Стандартный workflow разработки |

Правильная стратегия: seed-скрипты для стандартного набора тестовых данных, бэкапы — для экстренного восстановления конкретного состояния.

Пример seed-скрипта на Python (Django):

# management/commands/seed.py
from django.core.management.base import BaseCommand
from myapp.models import User, Product

class Command(BaseCommand):
    help = 'Seed database with test data'

    def handle(self, *args, **options):
        User.objects.get_or_create(email='admin@test.com', defaults={'name': 'Admin'})
        Product.objects.bulk_create([
            Product(name='Товар 1', price=100),
            Product(name='Товар 2', price=200),
        ], ignore_conflicts=True)
        self.stdout.write('База данных заполнена тестовыми данными')

Автоматизация бэкапов: скрипт для разработчика

Вот универсальный bash-скрипт для ежедневных бэкапов в процессе разработки:

#!/bin/bash
# db-backup.sh — запускайте из корня проекта

BACKUP_DIR="./backups"
MAX_BACKUPS=10  # Хранить последние 10 бэкапов
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

mkdir -p "$BACKUP_DIR"

# SQLite
if [ -f "app.db" ]; then
    sqlite3 app.db ".backup '$BACKUP_DIR/sqlite_$TIMESTAMP.db'"
    echo "SQLite бэкап создан"
fi

# PostgreSQL
if command -v pg_dump &> /dev/null; then
    pg_dump -h localhost -U postgres -Fc mydb > "$BACKUP_DIR/pg_$TIMESTAMP.dump" 2>/dev/null
    echo "PostgreSQL бэкап создан"
fi

# Удаляем старые бэкапы
ls -t "$BACKUP_DIR"/*.db 2>/dev/null | tail -n +$((MAX_BACKUPS+1)) | xargs rm -f
ls -t "$BACKUP_DIR"/*.dump 2>/dev/null | tail -n +$((MAX_BACKUPS+1)) | xargs rm -f

echo "Готово. Бэкапов сохранено: $(ls $BACKUP_DIR | wc -l)"

Добавьте в package.json или Makefile и запускайте перед рискованными операциями.


Инструменты для управления локальными бэкапами

DBeaver (бесплатный, все СУБД)

Визуальный клиент для всех популярных баз данных. Умеет экспортировать данные в SQL, CSV, Excel одним кликом. Подходит для разовых ручных бэкапов. Сайт: dbeaver.io

TablePlus (macOS, Windows, Linux)

Лёгкий и быстрый клиент. Поддерживает PostgreSQL, MySQL, SQLite, MongoDB. Быстрый экспорт таблиц. Есть бесплатная версия. Сайт: tableplus.com

DataGrip (JetBrains, платный)

Мощный инструмент для профессионалов. Умеет делать дампы с настройками, сравнивать схемы, управлять миграциями. Подходит для сложных проектов. Сайт: jetbrains.com/datagrip

dbsend.ru

Если вам нужна автоматизация бэкапов с отправкой в облако (S3, Google Drive, Яндекс.Диск), сервис dbsend.ru позволяет настроить это одной строкой. Работает с SQLite, PostgreSQL и NoSQL. Удобно, если хотите перенести стратегию локальных бэкапов на продакшен без переработки.


Правило 3-2-1 для локальной разработки

Классическое правило резервного копирования работает и для локальной среды:

  • 3 копии данных
  • 2 разных носителя (локальный диск + облако)
  • 1 копия offsite (Google Drive, Яндекс.Диск, S3)

Для локальной разработки достаточно упрощённой версии: копия в папке проекта + периодическая синхронизация с облаком (хотя бы раз в неделю).


Хранение бэкапов в облаке из командной строки

Google Drive через rclone

# Установка rclone и настройка Google Drive
rclone copy ./backups gdrive:dev-backups/myproject/

# Синхронизация (удаляет старые файлы на Drive)
rclone sync ./backups gdrive:dev-backups/myproject/ --max-age 30d

Яндекс.Диск через WebDAV

curl -T backup.sql \
  "https://webdav.yandex.ru/dev-backups/backup_$(date +%Y%m%d).sql" \
  -u "login:app_password"

Чек-лист бэкапов для разработчика

Сохраните и повесьте рядом с монитором:

  • Перед любой миграцией — бэкап базы
  • Перед docker-compose down -v — проверьте, нужны ли данные из volumes
  • Перед экспериментами с данными — бэкап
  • После долгого наполнения базы тестовыми данными — бэкап
  • Раз в день при активной разработке — автоматический бэкап по cron/планировщику
  • Проверяйте, что бэкап восстанавливается — раз в неделю

FAQ

Нужно ли бэкапить локальную базу, если в проекте есть миграции? Да. Миграции восстанавливают схему (таблицы, индексы), но не данные. Если у вас есть 500 строк тестовых данных, которые вы вносили вручную — они исчезнут без бэкапа.

Можно ли добавить SQLite-файл в Git? Технически можно, но не рекомендуется: бинарный файл плохо версионируется (огромные diff-ы), конфликты неразрешимы. Используйте .gitignore для .db и .dump файлов, а вместо этого пишите seed-скрипты.

Как быстро сделать бэкап PostgreSQL перед миграцией? pg_dump -h localhost -U postgres -Fc mydb > pre_migration_backup.dump. Одна команда, 5 секунд.

Что делать, если docker-compose down -v уже выполнен и данные удалены? Если volume не был примонтирован к хосту — восстановить невозможно. На будущее: всегда используйте named volumes или bind mounts с путём на хосте. Именно поэтому бэкапы нужны заранее.

Как автоматически делать бэкап перед каждым запуском миграций? Добавьте npm pre-hook. В package.json: "premigrate": "npm run db:backup". Теперь при npm run migrate сначала создастся бэкап.

Какой инструмент выбрать для бэкапов при разработке? Для SQLite — встроенная команда .backup. Для PostgreSQL — pg_dump. Для GUI — DBeaver (бесплатный). Для автоматического облачного бэкапа — dbsend.ru.

Сколько хранить локальные бэкапы? Для активной разработки достаточно 5-10 последних копий. Скрипт выше автоматически удаляет старые. На диске это займёт несколько десятков мегабайт.