Docker Postgresのスクリプトでユーザー/データベースを作成する方法


213

カスタムユーザーとデータベースを作成して、開発postgresインスタンスのコンテナを設定しようとしています。私は公式のpostgres dockerイメージを使用しています。ドキュメントでは、/docker-entrypoint-initdb.d/カスタムパラメータを使用してデータベースを設定するために、フォルダ内にbashスクリプトを挿入するように指示しています。

私の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

編集-2015年7月23日以降

画像ドッカ公式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/

ただし、2015年7月8日以降、ユーザーとデータベースを作成するだけでよい場合はPOSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_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

2015年7月23日より前の画像

以下からのpostgresドッカーイメージのドキュメント、次のことが言われています

[...] /docker-entrypoint-initdb.dサービスを開始する前に、さらに初期化を行うために、そのディレクトリにある* .shスクリプトをソースします[ ]

ここで重要なのは、「サービスを開始する前に」です。つまり、スクリプト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
DarVar

3
--singleは、どのpostgres Dockerfilesでもサポートされなくなりました。
brianz 2015

1
手順に従って、mysqlコンテナーにsshしてcdすると、SQLコードが含まれているdocker-entrypoint-initdb.dことがわかりinit.sqlます。しかし、mysqlを開き(rootアクセスを使用)、show databasesと入力すると、docker-compose.ymlファイルからはデフォルトのみが表示されます!なぜうまくいかないのですか?
Mahmoud Zalt 2016年

1
db.sql`docker
entrypoint

16

これで、.sqlファイルをinitディレクトリ内に配置できます。

ドキュメントから

このイメージから派生したイメージで追加の初期化を行う場合は、/ docker-entrypoint-initdb.dに1つ以上の* .sqlまたは* .shスクリプトを追加します(必要に応じてディレクトリを作成します)。エントリーポイントがinitdbを呼び出してデフォルトのpostgresユーザーとデータベースを作成すると、サービスを開始する前に、*。sqlファイルが実行され、そのディレクトリにある* .shスクリプトが読み込まれ、さらに初期化されます。

したがって、.sqlファイルのコピーは機能します。


ユーザー/パスワードおよびデータベース作成の環境変数は引き続き機能します。(9.5.3)
エレミヤアダムス

1
ローカルで機能するプロジェクトがあります。しかし、それをAWS EC2に移動すると、DBが見つからないと表示されます。.sqlファイルを適切なディレクトリにコピーしましたが、それでもそのエラーが返されます。どこを見ればいいのか?Dockerは初めてです。
MadPhysicist 2016年

1
これは、単一のボリュームにバインドされた単一のdbインスタンスがある場合にのみ当てはまります。つまり、ボリュームフォルダーに何かが既にある場合、スクリプトは実行されません。スタックサービスごとに個別のdb初期化子を用意したいので、これは頭痛の種です。
バイオレットレッド

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:
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.