Как создать 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