Бэкапы при локальной разработке: почему разработчики теряют данные и как этого избежать
Большинство разработчиков делают бэкапы продакшена и игнорируют локальную среду — до первого момента, когда случайная команда удаляет три часа ручной настройки тестовых данных. Короткий ответ на вопрос «надо ли бэкапить локальную базу»: да, и это занимает одну минуту настройки.
Почему локальные данные важнее, чем кажется
Продакшен обычно защищён: облачные провайдеры делают автоматические снапшоты, есть мониторинг, алерты. Локальная среда разработчика — это дикий запад.
Типичные сценарии потери данных на локальной машине:
- Запущена миграция с ошибкой — данные в нескольких таблицах стёрты
- 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 последних копий. Скрипт выше автоматически удаляет старые. На диске это займёт несколько десятков мегабайт.