Резервная копия PostgreSQL в Docker Compose: проверяем восстановление
Ночной скрипт сохранил app.dump, файл ненулевой, команда завершилась успешно. Этого достаточно, чтобы считать выгрузку созданной, но недостаточно для ответа на главный вопрос: сколько времени займёт восстановление и получится ли открыть приложение с этими данными? Проверим архив на отдельной PostgreSQL. Рабочий каталог данных и восстановленная база не должны пересекаться.
Что именно копируем
Ниже рабочий Compose уже содержит сервис db с PostgreSQL 18, базой app и пользователем app. Команды исполняются из каталога этого проекта; учётная запись должна иметь права выгрузить нужные объекты. pg_dump создаёт согласованную логическую копию одной базы. Роли и другие общие объекты кластера в неё не входят, как и возможность восстановиться на произвольную секунду между копиями. Для требований к малой потере данных нужен отдельный план резервирования с архивированием WAL.
Не копируйте файлы работающего volume обычным архиватором в надежде получить согласованную базу. В этой процедуре PostgreSQL сам формирует логический архив. Формат custom выбран для pg_restore: можно прочитать список объектов и управлять восстановлением. Версию утилит согласуйте с сервером; самый простой учебный вариант — запускать pg_dump из того же сервиса db.
docker compose exec -T db pg_dump -U app -d app -Fc -f /tmp/app-20261029.dump
docker compose cp db:/tmp/app-20261029.dump ./app-20261029.dump
docker compose exec -T db pg_restore --list /tmp/app-20261029.dumpКаждую следующую команду выполняйте только после успешного кода завершения предыдущей. Флаг -T отключает псевдотерминал. Бинарный архив сначала пишется в контейнере, затем копируется как файл: это позволяет избежать различий shell при перенаправлении бинарного stdout, особенно в старой Windows PowerShell. Убедитесь, что для временного файла достаточно места; большой дамп лучше сразу писать в выделенный каталог резервирования с контролируемыми правами.
Список pg_restore --list подтверждает читаемость структуры архива, но не выполняет SQL и не доказывает восстановимость всех объектов. Запишите время начала и окончания выгрузки, размер и контрольную сумму файла. Архив содержит данные приложения, поэтому доступ, шифрование и срок хранения должны соответствовать этим данным. Копия на том же диске, что и рабочая база, не защищает от потери этого диска.
Поднимаем независимую цель восстановления
Создайте отдельный каталог восстановления, скопируйте в него app-20261029.dump и перейдите в этот каталог. Здесь сохраните следующий файл как restore.compose.yaml и выполняйте все последующие команды восстановления. Здесь нет published ports и нет подключения рабочего volume. Учебный пароль используется только для изолированной локальной проверки; реальные данные требуют принятого в проекте способа передачи секретов. PostgreSQL 18 хранит данные в volume, смонтированном в /var/lib/postgresql, согласно устройству актуального официального образа.
services:
restore-db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: restore-lab-only
POSTGRES_DB: app_restore
volumes:
- restore-data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app_restore"]
interval: 2s
timeout: 2s
retries: 30
volumes:
restore-data: {}docker compose -p restorecheck -f restore.compose.yaml config --quiet
docker compose -p restorecheck -f restore.compose.yaml up -d --wait --wait-timeout 90
docker compose -p restorecheck -f restore.compose.yaml cp ./app-20261029.dump restore-db:/tmp/app.dump
docker compose -p restorecheck -f restore.compose.yaml exec -T restore-db pg_restore --exit-on-error --no-owner --no-acl -U app -d app_restore /tmp/app.dumpИспользуйте новое имя проекта для каждого независимого теста либо заранее проверяйте, что restorecheck ещё не существует. Иначе Compose повторно подключит прежний volume. База app_restore должна быть пустой. --exit-on-error останавливает восстановление на ошибке; --no-owner и --no-acl упрощают учебную цель, где нет исходных ролей. Это осознанно исключает проверку владельцев и прав. Если задача включает восстановление прав доступа, подготовьте роли и отдельный тест без такого упрощения.
Проверяем данные и возможность работы
После успешного восстановления выполните запросы к доменно важным таблицам. Для приложения заказов можно проверить число заказов и крайние даты, затем прочитать конкретный известный заказ. Имена ниже — пример контракта приложения: замените их своей схемой, не объявляйте отсутствие таблицы проблемой архива без сравнения с исходной базой.
docker compose -p restorecheck -f restore.compose.yaml exec -T restore-db psql -v ON_ERROR_STOP=1 -U app -d app_restore -c 'SELECT count(*), min(created_at), max(created_at) FROM orders;'Ожидаемые значения фиксируйте для состояния выгрузки. Если рабочая база продолжала принимать записи, её текущее число заказов закономерно окажется больше. Добавьте проверку миграционной версии и запуск совместимой версии приложения на восстановленной базе без доступа к рабочим внешним интеграциям. Это обнаружит отсутствующие расширения, права и зависимости, которых не видно по одному count.
Если восстановление требует расширений, подготовьте целевой образ с теми же доступными расширениями и совместимыми версиями. pg_dump сохранит описание объектов, но не установит отсутствующий системный пакет внутри контейнера. Ошибка CREATE EXTENSION при восстановлении — полезный результат теста: она показывает, что одного архива для выбранной цели недостаточно. В протоколе перечислите необходимый образ PostgreSQL и дополнительные компоненты, чтобы восстановление не зависело от памяти администратора.
Также проверьте последовательности и возможность вставки новой строки в копию. Чтение старых данных может работать, а права записи или состояние генератора идентификаторов — нет. Такой тест выполняйте только в восстановленном окружении. Измеряйте весь путь от получения файла до успешного запроса приложения: время самого pg_restore не включает доставку архива, запуск сервера и подготовку ролей, хотя при аварии эти этапы тоже придётся пройти.
Результат теста — успешное восстановление, проверенные данные и измеренное время до рабочего состояния. Сохраните журнал отдельно от архива и повторяйте процедуру после изменений версии PostgreSQL и расширений. Срок хранения и допустимую потерю данных определяют требования самого сервиса.
Ещё по теме
- Обновление приложения в Docker Compose: фиксируем версию и готовим откат
- Compose override добавил второй порт вместо замены: проверяем объединение файлов
Продолжить изучение
Хотите разобраться в контейнеризации целиком, от образа до работающего окружения? Сборка, сети, данные и запуск приложений входят в программу «Docker и Docker Compose: контейнеризация приложений».
Продолжить на практике
- Docker и Docker Compose: контейнеризация приложений ↗
Упакуйте приложение в Docker и запустите его с PostgreSQL через Compose. Образы, сети, тома, диагностика поломок, обновление версий и восстановление данных — с практикой и итоговым проектом.
