Использование docker-compose для создания таблиц в базе данных postgresql

Я использую docker-compose для развертывания многоконфигурирующего приложения python Flask. Мне сложно понять, как создавать таблицы в базе данных postgresql во время сборки, поэтому мне не нужно добавлять их вручную с помощью psql.

Мой файл docker-compose.yml:

web:
  restart: always
  build: ./web
  expose:
    - "8000"
  links:
    - postgres:postgres
  volumes:
    - /usr/src/flask-app/static
  env_file: .env
  command: /usr/local/bin/gunicorn -w 2 -b :8000 app:app

nginx:
  restart: always
  build: ./nginx/
  ports:
    - "80:80"
  volumes:
    - /www/static
  volumes_from:
    - web
  links:
    - web:web

data:
  restart: always
  image: postgres:latest
  volumes:
    - /var/lib/postgresql
  command: "true"

postgres:
  restart: always
  image: postgres:latest
  volumes_from:
    - data
  ports:
    - "5432:5432"

Я не хочу вводить psql для ввода:

CREATE DATABASE my_database;
CREATE USER this_user WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE "my_database" to this_user;
\i create_tables.sql

Я был бы признателен за руководство по созданию таблиц.

Ответ 1

Я не хочу вводить psql для ввода

Вы можете просто использовать встроенный механизм инициализации контейнера:

COPY init.sql /docker-entrypoint-initdb.d/10-init.sql

Это гарантирует, что ваш sql будет выполнен после правильной загрузки сервера БД.

Взгляните на свою точку входа script. Он делает некоторые приготовления для правильного запуска psql и ищет каталог /docker-entrypoint-initdb.d/ для файлов, заканчивающихся на .sh, .sql и .sql.gz.

10- в имени файла происходит потому, что файлы обрабатываются в порядке ASCII. Вы можете назвать ваши другие файлы инициализации, например, 20-create-tables.sql и 30-seed-tables.sql.gz, и убедитесь, что они обработаны по мере необходимости.

Также обратите внимание, что команда вызова не определяет базу данных. Имейте это в виду, если вы, скажем, переходите на docker-compose, и ваши существующие файлы .sql также не указывают DB.

Ваши файлы будут обрабатываться при первом запуске контейнера, установленном на этапе build. Поскольку Docker Compose останавливает изображения, а затем возобновляет их, практически нет разницы, но если для вас важно начать работу с базой данных на этапе build, я предлагаю использовать встроенный метод init, вызывая /docker-entrypoint.sh из вашего файла docker, а затем очистка вверх в директории /docker-entrypoint-initdb.d/.

Ответ 2

Я бы создал таблицы как часть процесса сборки. Создайте новый Dockerfile в новом каталоге ./database/

FROM postgres:latest
COPY . /fixtures
WORKDIR /fixtures
RUN /fixtures/setup.sh

./database/setup.sh будет выглядеть примерно так:

#!/bin/bash
set -e

/etc/init.d/postgresql start
psql -f create_fixtures.sql    
/etc/init.d/postgresql stop

Поместите своего создателя, создайте базу данных, создайте таблицу sql (и любые другие данные прибора) в файл create_fixtures.sql в каталоге ./database/.

и, наконец, ваша служба postgres изменится на использование build:

postgres:
    build: ./database/
    ...

Примечание. Иногда после /etc/init.d/postgresql start вам понадобится sleep 5 (или даже лучше script для опроса и дождитесь запуска postgresql). По моему опыту, для него это отвечает как init script, так и psql, но я знаю, что это не так с mysql, поэтому я подумал, что позвоню.