Как создать пользователя / базу данных в скрипте для Docker Postgres


213

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

Мой скрипт bash: 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? Есть ли способ сделать это с помощью скрипта?

Ответы:


378

РЕДАКТИРОВАТЬ - с 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
Вы можете с:gosu postgres postgres --single < /tmp/somefile.sql
— Thomasleveil

1
Как я могу бежатьpsql -U myDb -d myDb -f myDb.sql
— ДарВар

3
Обратите внимание, --single больше не поддерживается ни в одном из файлов Docker Postgres.
— Брианц

1
Я следовал за шагами и когда я ssh в контейнер mysql и CD в, docker-entrypoint-initdb.dя вижу мой init.sqlс кодом sql в нем. НО, когда я открываю mysql (используя root-доступ) и набираю show database, я вижу только значение по умолчанию из docker-compose.ymlфайла! Почему это не работает для меня?
— Махмуд Залт

1
Он не выполняется db.sqlдаже после того, как он скопирован в `docker-entrypoint-initdb.d`
— kamal

16

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

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

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

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


переменные окружения для создания пользователя / пароля и создания БД все еще работают. (9.5.3)
— Иеремия Адамс

1
У меня есть проект, который работает на местном уровне. Однако, когда я перемещаю его в AWS EC2, он говорит, что DB не найдена. Я копирую файл .sql в соответствующий каталог, но он все равно возвращает эту ошибку. Есть идеи, где я могу посмотреть? Я новичок в Докере.
— MadPhysicist

1
Это верно только в том случае, если существует один экземпляр БД, связанный с одним томом, т.е. он не будет запускать сценарии, если что-либо уже находится в папке тома. Это доставляет мне головную боль, потому что я хочу иметь отдельные инициализаторы БД для каждого из моих стековых сервисов.
— Фиолетовый Красный

Из документов Warning: scripts in /docker-entrypoint-initdb.d are only run if you start the container with a data directory that is empty; any pre-existing database will be left untouched on container startup. One common problem is that if one of your /docker-entrypoint-initdb.d scripts fails (which will cause the entrypoint script to exit) and your orchestrator restarts the container with the already initialized data directory, it will not continue on with your scripts.
— sh87

9

Используя 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

8

Я добавляю пользовательские команды в среду, вызванную в 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>

,


7

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

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;"

3
ENCODING 'LATIN1'очень странно ... Вы должны иметь особые потребности избегать использования utf8
— Zyigh

4

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

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


2

С docker compose есть простая альтернатива (не нужно создавать Dockerfile). Просто создайте init-database.sh:

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE USER docker;
    CREATE DATABASE my_project_development;
    GRANT ALL PRIVILEGES ON DATABASE my_project_development TO docker;
    CREATE DATABASE my_project_test;
    GRANT ALL PRIVILEGES ON DATABASE my_project_test TO docker;
EOSQL

И сослаться на это в разделе томов:

version: '3.4'

services:
  postgres:
    image: postgres
    restart: unless-stopped
    volumes:
      - postgres:/var/lib/postgresql/data
      - ./init-database.sh:/docker-entrypoint-initdb.d/init-database.sh
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    ports:
      - 5432:5432

volumes:
  postgres:
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.