Другое

Как вставить данные в PostgreSQL Docker контейнер

Узнайте, как корректно загружать данные из файлов SQL хоста в контейнер PostgreSQL Docker с помощью перенаправления, копирования файлов или инициализации Dockerfile.

Как правильно загрузить образцы данных в PostgreSQL, работающий в Docker‑контейнере?

Я запускаю базу PostgreSQL в Docker‑контейнере и хочу импортировать данные из SQL‑файла, расположенного на хосте. Я попробовал выполнить следующую команду:

bash
docker exec -it postgres bash psql "postgres://postgres:postgres@localhost/test" -f ./prepare_source_data.sql

Но она выдаёт несколько ошибок:

/usr/bin/psql: line 19: use: command not found
/usr/bin/psql: line 20: use: command not found
/usr/bin/psql: line 21: use: command not found
/usr/bin/psql: line 22: use: command not found
/usr/bin/psql: psql: line 24: syntax error near unexpected token `$version,'
/usr/bin/psql: psql: line 24: `my ($version, $cluster);'

Интересно, что следующие команды работают корректно, если их выполнять по очереди:

bash
docker exec -it postgres bash
psql -U postgres

Как правильно загрузить данные из SQL‑файла, находящегося на стороне хоста, в контейнер PostgreSQL?

Для загрузки образца данных из SQL‑файла на хосте в базу PostgreSQL, работающую в контейнере Docker, необходимо использовать правильный синтаксис команды docker exec. Текущий подход не работает, потому что вы пытаетесь выполнить несколько команд в одном вызове docker exec без корректной обработки оболочки.

Правильный способ загрузки данных из файла SQL на хосте в контейнер PostgreSQL – использовать перенаправление ввода с командой docker exec. Ниже приведены работающие методы:

Содержание

Использование перенаправления ввода

Самый эффективный способ – использовать перенаправление ввода с командой docker exec:

bash
docker exec -i postgres psql -U postgres -d test < ./prepare_source_data.sql

Пояснение:

  • -i – держит STDIN открытым, чтобы контейнер мог принимать ввод
  • psql -U postgres -d test подключается к базе PostgreSQL
  • < ./prepare_source_data.sql перенаправляет содержимое SQL‑файла в psql

Этот подход рекомендован экспертами Stack Overflow и работает напрямую с файлами на вашей машине хоста.

Копирование файла в контейнер сначала

В качестве альтернативы можно сначала скопировать SQL‑файл в контейнер, а затем выполнить его:

bash
# Шаг 1: Копируем SQL‑файл в контейнер
docker cp ./prepare_source_data.sql postgres:/tmp/

# Шаг 2: Выполняем SQL‑файл изнутри контейнера
docker exec -i postgres psql -U postgres -d test -f /tmp/prepare_source_data.sql

Преимущества:

  • Файл хранится внутри контейнера для дальнейшего использования
  • Можно проверить, что файл скопирован корректно
  • Полезно для больших файлов, где потоковое чтение может быть проблематичным

Этот метод описан в обсуждениях сообщества Docker и обеспечивает лучший контроль над расположением файла.

Использование Dockerfile для первоначальной загрузки данных

Если вам нужно загрузить данные при первом создании контейнера, можно использовать подход Dockerfile с каталогом docker-entrypoint-initdb.d:

dockerfile
FROM postgres:latest
COPY prepare_source_data.sql /docker-entrypoint-initdb.d/

Затем соберите и запустите контейнер:

bash
docker build -t postgres-with-data .
docker run --name postgres -d -p 5432:5432 postgres-with-data

Важно: Этот метод работает только при первом создании контейнера и когда каталог данных пуст. Как отмечено в этой статье, скрипты в docker-entrypoint-initdb.d/ выполняются во время инициализации контейнера.

Общие ошибки и их устранение

Почему ваш исходный запрос не сработал:

bash
docker exec -it postgres bash psql "postgres://postgres:postgres@localhost/test" -f ./prepare_source_data.sql

Проблемы:

  1. Несколько команд без правильного экранирования: вы пытаетесь запустить bash, а затем psql в одной команде
  2. Относительный путь: путь ./prepare_source_data.sql считается относительно рабочей директории контейнера, а не хоста
  3. Формат строки подключения: использование URI‑формата с флагом -f не поддерживается

Альтернативный рабочий синтаксис:

Если вы предпочитаете интерактивный подход, нужно разделить команды:

bash
docker exec -it postgres bash
# Внутри контейнера:
psql -U postgres -d test -f /path/to/prepare_source_data.sql

Но сначала необходимо скопировать файл в контейнер с помощью docker cp.

Лучшие практики импорта данных

Для больших SQL‑файлов

При работе с большими файлами рассмотрите следующие оптимизации:

bash
# Используйте одну транзакцию для лучшей производительности
docker exec -i postgres psql -U postgres -d test -1 < ./large_file.sql

# Для очень больших файлов разбейте их на более мелкие части и обрабатывайте последовательно

Параметры подключения к базе

Всегда проверяйте параметры подключения:

  • -U postgres: пользователь PostgreSQL (по умолчанию postgres)
  • -d test: имя базы данных
  • -h localhost: хост (необязательно, по умолчанию localhost)
  • -p 5432: порт (необязательно, по умолчанию 5432)

Обработка ошибок

Добавьте обработку ошибок в процесс импорта:

bash
# Проверяем, был ли импорт успешным
if docker exec -i postgres psql -U postgres -d test < ./prepare_source_data.sql; then
    echo "Данные успешно импортированы"
else
    echo "Ошибка импорта данных"
    exit 1
fi

Соображения безопасности

  • Используйте переменные окружения для учетных данных, а не жёстко кодируйте их
  • Рассмотрите возможность использования файла .pgpass для автоматизированных подключений
  • Ограничьте права доступа к вашим SQL‑файлам

Метод перенаправления ввода (docker exec -i <контейнер> psql -U <пользователь> -d <база> < <файл>.sql) является самым простым и рекомендуемым способом загрузки данных из файлов SQL на хосте в контейнер PostgreSQL, поскольку он избегает сложности копирования файлов и эффективно обрабатывает большие файлы.

Источники

  1. Stack Overflow – Как восстановить базу данных из дампа или SQL‑файла в Docker с использованием тома?
  2. DEV Community – Как импортировать SQL‑файл в Docker‑изолированную базу PostgreSQL
  3. Блог Mat Duggan – Правильный способ загрузки SQL‑файлов в контейнер PostgreSQL Docker
  4. Документация Docker – Предварительное заполнение базы данных
  5. Chicago Architecture Biennial – Docker PostgreSQL: Импорт базы данных как профессионал

Заключение

Чтобы успешно загрузить образец данных из SQL‑файла на хосте в ваш контейнер PostgreSQL:

  1. Используйте перенаправление вводаdocker exec -i postgres psql -U postgres -d test < ./your_file.sql – самый эффективный метод
  2. Избегайте выполнения нескольких команд в одном docker exec – ваш исходный подход не сработал, потому что bash не смог корректно обработать команду psql
  3. Учитывайте размер файла – для больших файлов используйте флаг -1 для обработки в одной транзакции
  4. Проверьте учётные данные – убедитесь, что имя базы, пользователь и параметры подключения корректны
  5. Тестируйте сначала с небольшими файлами – подтвердите настройку с простым SQL‑файлом, прежде чем импортировать большие наборы данных

Метод перенаправления ввода обеспечивает самый чистый и надёжный способ загрузки данных напрямую с вашего хоста без необходимости предварительного копирования файлов.

Авторы
Проверено модерацией
Модерация