Как создать User/Database в script для Docker Postgres

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

Мой bash script: make_db.sh

su postgres -c "createuser -w -d -r -s docker"
su postgres -c "createdb -O docker docker"

Dockerfile

FROM library/postgres

RUN ["mkdir", "/docker-entrypoint-initdb.d"]
ADD make_db.sh /docker-entrypoint-initdb.d/

Ошибка, полученная из docker logs -f db (db - мое имя контейнера):

createuser: не удалось подключиться к базе данных postgres: не удалось подключиться к серверу: нет такого файла или каталога

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

Ответ 1

ОБНОВЛЕНИЕ - с 23 июля 2015 года

Официальный образ докера postgres запустит сценарии .sql, найденные в папке /docker-entrypoint-initdb.d/.

Поэтому все, что вам нужно, это создать следующий скрипт sql:

init.sql

CREATE USER docker;
CREATE DATABASE docker;
GRANT ALL PRIVILEGES ON DATABASE docker TO docker;

и добавьте его в свой Dockerfile:

Dockerfile

FROM library/postgres
COPY init.sql /docker-entrypoint-initdb.d/

Но с 8 июля 2015 года, если вам нужно только создать пользователя и базу данных, проще использовать переменные окружения POSTGRES_USER, POSTGRES_PASSWORD и POSTGRES_DB:

docker run -e POSTGRES_USER=docker -e POSTGRES_PASSWORD=docker -e POSTGRES_DB=docker library/postgres

или с Dockerfile:

FROM library/postgres
ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker
ENV POSTGRES_DB docker

для изображений старше 23 июля 2015 года

Из документации по изображению Postgres Docker сказано, что

[...] он будет использовать любой сценарий *.sh, найденный в этом каталоге [/docker-entrypoint-initdb.d], чтобы выполнить дальнейшую инициализацию перед запуском службы

Что здесь важно, так это "до запуска сервиса". Это означает, что ваш скрипт make_db.sh будет выполнен до запуска службы postgres, поэтому появляется сообщение об ошибке "Не удалось подключиться к базе данных postgres".

После этого есть еще одна полезная информация:

Если вам нужно выполнить команды SQL в процессе инициализации, настоятельно рекомендуется использовать однопользовательский режим Postgres.

Согласитесь, это может быть немного загадочно на первый взгляд. Это говорит о том, что ваш скрипт инициализации должен запустить службу postgres в одиночном режиме перед выполнением его действий. Таким образом, вы можете изменить свой скрипт make_db.ksh следующим образом, и он должен приблизить вас к тому, что вы хотите:

ПРИМЕЧАНИЕ, это недавно изменилось в следующем коммите. Это будет работать с последним изменением:

export PGUSER=postgres
psql <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL

Ранее было необходимо использовать режим --single:

gosu postgres postgres --single <<- EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL

Ответ 2

Теперь вы можете поместить файлы .sql в каталог init:

Из документов

Если вы хотите выполнить дополнительную инициализацию в образе, полученном из этого, добавьте один или несколько сценариев *.sql или *.sh в /docker-entrypoint-initdb.d (создавая каталог при необходимости). После того, как точка входа вызовет initdb для создания пользователя и базы данных postgres по умолчанию, она запустит любые файлы *.sql и найдет все сценарии *.sh, найденные в этом каталоге, для дальнейшей инициализации перед запуском службы.

Так что копирование вашего .sql файла в будет работать.

Ответ 3

Я добавляю пользовательские команды в среду, вызванную в CMD после запуска служб... Я не делал этого с postgres, но с Oracle:

#set up var with noop command
RUN export POST_START_CMDS=":"
RUN mkdir /scripts
ADD script.sql /scripts
CMD service oracle-xe start; $POST_START_CMDS; tail -f /var/log/dmesg

и начните с

docker run -d ... -e POST_START_CMDS="su - oracle -c 'sqlplus @/scripts/script' " <image>

.

Ответ 4

Вам нужно, чтобы база данных работала до создания пользователей. Для этого вам нужно несколько процессов. Вы можете запускать postgres в подоболочке (&) в оболочке script или использовать инструмент типа supervisord для запуска postgres, а затем запускать любые скрипты инициализации.

Руководство по супервизору и докеру https://docs.docker.com/articles/using_supervisord/

Ответ 5

Вы можете использовать эти команды:

docker exec -it yournamecontainer psql -U postgres -c "CREATE DATABASE mydatabase ENCODING 'LATIN1' TEMPLATE template0 LC_COLLATE 'C' LC_CTYPE 'C';"

docker exec -it yournamecontainer psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE postgres TO postgres;"

Ответ 6

Используя docker-compose:

Предполагая, что у вас есть следующая структура каталогов:

$MYAPP_ROOT/docker-compose.yml
           /Docker/init.sql
           /Docker/db.Dockerfile

Файл: docker-compose.yml

version: "3.3"
services:
  db:
    build:
      context: ./Docker
      dockerfile: db.Dockerfile
    volumes:
      - ./var/pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

Файл: Docker/init.sql

CREATE USER myUser;

CREATE DATABASE myApp_dev;
GRANT ALL PRIVILEGES ON DATABASE myApp_dev TO myUser;

CREATE DATABASE myApp_test;
GRANT ALL PRIVILEGES ON DATABASE myApp_test TO myUser;

Файл: Docker/db.Dockerfile

FROM postgres:11.5-alpine
COPY init.sql /docker-entrypoint-initdb.d/

Создание и запуск сервисов:

docker-compose -f docker-compose.yml up --no-start
docker-compose -f docker-compose.yml start