Как создать пользователя / базу данных в скрипте для 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.