Сложилось так исторически, что мы долго не обновляли PostgreSQL и застряли на версии 12. Но пришло время обновлять зависимости проекта и оказалось, что Django 5.1 версию 12 PostgreSQL уже не поддерживает и это мотивировало меня провести обновление до новейшей 16 версии.
На момент написания у нас всё организовано достаточно просто — все необходимые компоненты запускаются в Docker-контейнерах через Docker Compose.
У меня было два варианта, как произвести миграцию:
-
Сделать полный дамп, загрузить новый образ
postgres:16
и накатить дамп -
Использовать утилиту
pg_upgrade
, которая позволяет мигрировать данные между версиями PostgreSQL
Поскольку первый метод требует больше времени на восстановление данных, я решил воспользоваться вторым вариантом — pg_upgrade
. Плюс, этот вариант давал возможность попробовать что-то новое.
Сначала было непонятно как применить pg_upgrade
в docker, но после непродолжительного гуглежа я нашёл решение: https://github.com/tianon/docker-postgres-upgrade
По ходу изучения того, как работать с docker-postgres-upgrade
был составлен такой план:
-
остановить сервисы, зависимые от БД
-
сделать бэкап БД
-
остановить БД
-
произвести миграцию
-
запустить и проверить БД на новой версии PostgreSQL
-
запустить сервисы
-
обновить docker-compose.yml
Примечание: хотя pg_upgrade
и позволяет произвести миграцию на горячую, но я решил не рисковать и сделать это на холодную
Ниже я кратко опишу процесс миграции.
Для начала нужно понять какой volume используется нашим PostgreSQL
% cat docker-compose.yml
services: ... postgres: image: postgres:12 container_name: postgres command: postgres -c "config_file=/etc/postgresql/postgresql.conf" environment: POSTGRES_PASSWORD: xxxxxx volumes: - ./postgresql/postgresql.conf:/etc/postgresql/postgresql.conf - postgres:/var/lib/postgresql/data ports: - "5432:5432" ... volumes: postgres:
% docker volume ls DRIVER VOLUME NAME local 1b7ffcbd614f280ab577370912c625135ef84fe8cf721953206ba0142bed8cad local 6b82aa6ecc19fbea9eb91b8d68af0d6a18d04911717953935cff006a4220e123 local 7c2b74aa668a47d2fe15615b8f4a614ebcf3065ab101cdaf487da6b5e1c95ffd local 16ea96ec68eeb0134f0eebd27ec983143e9bdd43d527d3c6e1d3f1cd2bacc516 local 180aeeeadba249e991c22bb77c53c9b2a50612a3d181598a8014b667d920762d local 625ebc83103e8c223395fb7b5e7e31a714110400f6f70f499bee13f3d9b86bce local 803c056ecb2c83b31e5d0dbb089689ae1b44996fb84aee1e12c8d224b583f8e7 local a1ccdb17c4cc50333ec2c417cf24553e89e4f5aa1e402c1985a8fec2f52c00dd local a40c9d1b958169dda6db47e7493dacf7c05e6e0acd678954ea87f7ac3ffb8a16 local backend_media local backend_postgres local backend_postgres-14 local backend_postgres-16 local backend_static local c73a013579341af8a05646a501f4b4a9595a3e2b1167543889d1c26a21e4fda3 local cebd974e3e2f2a5bd0b2cf16a4ef293696e30d547ccfd59bad44d155541da16b local d393b6d74083d4ac5a679a7ed62cf364663a66fa41f113e1b60395ec369e26bb local dev_badger local dev_media local dev_postgres local dev_static local edb6be7221e82a9f9c4ba47ac1cae104765bc8d4d29020fef1397aa4d22e9472 local minikube local minikube-m02 local postgres local postgres16 local qa-automation_badger local qa-automation_media local qa-automation_postgres local qa-automation_static
Нам нужен volume backend_postgres
, потому что Docker Compose по умолчанию именует volumes в формате «имя проекта + имя volume». Поскольку проект называется backend
(по-умолчанию имя каталога, где запускается Docker Compose, если не задано другое ключом -p
), наш целевой volume будет называться backend_postgres
. Для новой версии PostgreSQL volume будет называться backend_postgres16
.
миграция
% docker run --platform linux/amd64 --rm -v backend_postgres:/var/lib/postgresql/12/data -v backend_postgres16:/var/lib/postgresql/16/data tianon/postgres-upgrade:12-to-16
На MacOS с архитектурой Apple Silicon (M1/M2/M3) возникла необходимость добавить флаг --platform linux/amd64
, так как образ tianon/postgres-upgrade
по умолчанию не поддерживает ARM-архитектуру. Это позволяет принудительно использовать x86_64-образ для успешного запуска.
После завершения процедуры миграции делаем пробный запуск:
% docker run -dit --name postgres16 -p 5432:5432 -e POSTGRESS_PASSWORD=postgres -v backend_postgres16:/var/lib/postgresql/data -v ./postgresql/postgresql.conf:/var/lib/postgresql/data/postgresql.conf -v ./postgresql/pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf postgres:16
У меня кастомные postgresql.conf и pg_hba.conf поэтому прокидываем их внутрь контейнера.
И проверяем по логам, что всё хорошо
% docker logs -f postgres16
Нужно проверить логи на наличие ошибок или предупреждений. Особое внимание стоит уделить сообщениям о несовместимости версий или проблемах с доступом к данным.
Если тестовый запуск прошёл успешно, можно закрепить изменения в основном файле docker-compose.yml
, заменив старую версию PostgreSQL на новую. Важно убедиться, что все зависимости обновлены и настроены правильно перед запуском в продакшн.
Новый docker-compose.yml
services: ... postgres: image: postgres:16 container_name: postgres environment: POSTGRES_PASSWORD: xxxxxx volumes: - ./postgresql/postgresql.conf:/var/lib/postgresql/data/postgresql.conf - ./postgresql/pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf - postgres16:/var/lib/postgresql/data ports: - "5432:5432" ... volumes: postgres16:
Заключение
Благодаря docker-postgres-upgrade
процесс миграции на новую версию PostgreSQL прошёл быстро и гладко. Это отличное решение для тех, кто ищет простой и надёжный способ обновления PostgreSQL в Docker-среде. Рекомендую!
ссылка на оригинал статьи https://habr.com/ru/articles/837994/
Добавить комментарий