Обновление PostgreSQL между мажорными версиями задача не самая простая, недостаточно просто загрузить новый контейнер, нужно еще выполнить конвертацию структуры кластера СУБД, которая меняется от версии к версии.
Для небольших и средних баз идеально использовать импорт/экспорт при помощи утилиты pg_dumpall, что полностью исключает риск повреждения исходных данных, плюс у вас на руках всегда остается актуальная резервная копия в виде дампа всего кластера.
Итак, приступим, допустим мы изначально имеем:
services:
db:
container_name: postgres-db
В нашем случае:
▫️ db — имя сервиса Compose
▫️ postgres-db — реальное имя контейнера Docker
1️⃣ Остановим весь стек и запустим обратно только контейнер с СУБД, это исключит возможную запись в БД во время выгрузки:
docker compose stop
docker compose up -d db
Теперь выполним выгрузку дампа всего кластера:
docker exec -t postgres-db pg_dumpall -U postgres > full_backup.sql
Проверяем, что файл выгрузки создан. После чего останавливаем контейнер с БД:
docker compose down
2️⃣ Следующие шаги будут несколько различаться в отличие от того, используем ли мы Named Volumes или Bind mount, но в любом случае наша задача запустить новый контейнер СУБД с пустым томом.
🔹 Для Named Volumes было:
services:
db:
image: postgres:17
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
Стало:
services:
db:
image: postgres:18
volumes:
- pg_data_18:/var/lib/postgresql/data
volumes:
pg_data_18:
🔹 Для Bind mount было:
services:
db:
image: postgres:17
volumes:
- ./postgres-data:/var/lib/postgresql/data
Стало:
services:
db:
image: postgres:18
volumes:
- ./postgres-data-18:/var/lib/postgresql/data
3️⃣ Запускаем СУБД:
docker compose up -d db
Мы нее запускаем весь стек, чтобы раньше времени приложения не начали писать в новую чистую БД.
Ждем пока база инициализируется и готова будет принимать соединения, для этого выполним команду:
docker logs -f postgres-db
Как только появится сообщение:
database system is ready to accept connections
Можно двигаться дальше. Загружаем дамп кластера СУБД:
docker exec -i postgres-db psql -U postgres < full_backup.sql
Теперь запускаем весь стек:
docker compose up -d
4️⃣ После чего рекомендуется выполнить оптимизацию загруженной базы:
docker exec -it postgres-db vacuumdb -U postgres --all --analyze-only
Это не мешает работе и можно запускать уже на работающем стеке. Старые тома лучше всего оставить на некоторое время, пока вы не убедитесь, что обновление прошло нормально.
