К настоящему времени вы знаете, что контейнеры Docker никуда не денутся. Они обеспечивают согласованную среду разработки между различными хостами. Но как восстановить базу данных PostgreSQL (сокращенно psql) в контейнере Docker? В этой статье я рассказываю как.

Во-первых, как и большинство, вы, вероятно, думали, что сможете избежать этого следующим образом:

$ pg_restore --debug --clean --user ${POSTGRES_USER} \
  --dbname ${POSTGRES_DB} \
  -h ${DOCKER_IP} \
  ${DATABASE_DUMP}

И вы, несомненно, получаете ошибки. Если это удастся, вы один из немногих счастливчиков! Но в большинстве случаев вы получите какую-то ошибку. Для меня (на этот раз) получалось

segmentation fault (core dumped)  pg_restore --clean --user $POSTGRES_USER \
  --dbname $POSTGRES_DB \
  -h ${POSTGRES_HOST}

Хромой!

В других случаях я получал ошибку о несоответствии версии postgresql. По сути, pg_restore плохо совместим с другими версиями. Поэтому нам нужно использовать pg_restore для док-контейнера. как нам это сделать? Не так:

$ # Again, DON'T do it like this! Nothing bad will happen, it just
$ # won't work! 🤪
$ docker exec -it ${CONTAINER_ID} bash -c pg_restore -c \
  --user ${POSTGRES_USER} \
  --dbname ${POSTGRES_DB} \
  ./dump_file.db

Почему? Потому что, как только мы выполним bash, мы окажемся в контексте док-контейнера. dump_file.db не существует в контейнере. Приступим к решению.

Но сначала рекламная пауза…

Понравилось решение, которое я предлагаю?

💼 Наймите меня техническим руководителем в вашу команду. У меня более 10 лет опыта разработки, и я хотел бы помочь вашей команде полностью раскрыть свой потенциал. Перейдите на https://damngood.tech/pages/schedule.html, чтобы записаться на бесплатную консультацию.

Ладно, вперед и вверх!

Нам нужно docker cp файл базы данных в контейнер.

О, и небольшая подсказка... вот простой способ получить идентификатор контейнера:

$ export CONTAINER_ID=$(docker ps --format='{{.ID}}' --filter name=^/postgres$ --filter name=^/somename$)

Если вы хотите пропустить somename , не стесняйтесь. По сути, это имя, присвоенное док-контейнеру из docker compose как часть проекта. Я просто оставляю его там на случай, если у меня есть несколько контейнеров postgres.

Теперь давайте скопируем файл в контейнер докеров:

$ docker cp ${PG_FILE} ${CONTAINER_ID}:/dump.db

Теперь, когда он скопирован, мы можем выполнить pg_restore в работающем контейнере:

$ docker exec -it ${CONTAINER_ID} \
  bash -c 'pg_restore -c --user ${POSTGRES_USER} --dbname ${POSTGRES_DB} /dump.db'
$ # note: `-c` clears the database! Leave it off if you don't want to clear it.

И вы должны увидеть кучу вывода.

Вот программа в виде полного сценария BASH для вашего исполнения:

#!/bin/bash

# TODO: Store your POSTGRES_USER and POSTGRES_DB variables in .env
# (also add .env to .gitignore)
source .env

PG_FILE=${1}

if [[ -z "$PG_FILE" ]]; then
    echo "Please specify a PostgreSQL file"
    exit 1
fi

# TODO: replace/leave off somename.
CONTAINER_ID=$(docker ps --format='{{.ID}}' --filter name=^/postgres$ --filter name=^/somename$)

docker cp ${PG_FILE} ${CONTAINER_ID}:/dump.db

docker exec -it $CONTAINER_ID bash -c 'pg_restore -c --user ${POSTGRES_USER} --dbname ${POSTGRES_DB} /dump.db'

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

$ bash ./load_docker_db.sh ./my_db_snapshot.sql

Заключение

В этой статье я описал, как восстановить базу данных postgresql в контейнере Docker. Сначала нам нужно было скопировать базу данных в контейнер, а затем выполнить pg_restore внутри контейнера докеров.

📢 Комментарий ниже: Вы столкнулись с этой проблемой? Как вы обошли это?

👉‍‍ Поделитесь этой статьей с 3 своими друзьями или коллегами. В Twitter, LinkedIn или Mastodon. Обязательно отметьте меня в публикации. Помогает мне узнать, актуален ли мой контент.

💓 Подпишитесь на DamnGoodTech на Ko-Fi всего за 7 долларов в месяц. Получайте статьи на 3 дня раньше и получайте благодарность за каждую статью! Это все равно, что нанять тимлида в вашу компанию по разработке программного обеспечения за гораздо меньшую заработную плату. 🙏🏻 Особая благодарность Джеймсу Н., Люси Р. и Стиву О. за вашу поддержку.

💼 Наймите меня в качестве руководителя технического отдела. У меня более 10 лет опыта разработки, и я хотел бы помочь вашей команде полностью раскрыть свой потенциал. Перейдите на https://damngood.tech/pages/schedule.html, чтобы назначить бесплатную консультацию.