web-dev-qa-db-ja.com

DockerでPostgresコンテナーを開始してデータを取り込む

Postgresデータベースを含むDockerコンテナーがあります。公式の Postgres image を使用しています。これには、メインスレッドでサーバーを起動するCMDエントリがあります。

クエリのリッスンを開始する前に、RUN psql –U postgres postgres < /dump/dump.sqlを実行してデータベースにデータを入力します。

これがDockerでどのように可能かはわかりません。 CMDの後にRUNコマンドを配置した場合、DockerがDockerfileの読み取りを完了したため、もちろん到達しません。しかし、CMDの前に配置すると、psqlがプロセスとして存在する前に実行されます。

DockerでPostgresデータベースに事前入力するにはどうすればよいですか?

40
Miguel

多くの戦いの後、私は解決策を見つけました;-)

私にとって非常に便利なコメントがここに投稿されました: https://registry.hub.docker.com/_/postgres/ from "justfalter"

とにかく、私はこの方法でやった:

# Dockerfile
FROM postgres:9.4

RUN mkdir -p /tmp/psql_data/

COPY db/structure.sql /tmp/psql_data/
COPY scripts/init_docker_postgres.sh /docker-entrypoint-initdb.d/

db/structure.sqlはSQLダンプであり、最初のテーブルスペースを初期化するのに役立ちます。

そうして init_docker_postgres.sh

#!/bin/bash

# this script is run when the docker container is built
# it imports the base database structure and create the database for the tests

DATABASE_NAME="db_name"
DB_DUMP_LOCATION="/tmp/psql_data/structure.sql"

echo "*** CREATING DATABASE ***"

# create default database
gosu postgres postgres --single <<EOSQL
  CREATE DATABASE "$DATABASE_NAME";
  GRANT ALL PRIVILEGES ON DATABASE "$DATABASE_NAME" TO postgres;
EOSQL

# clean sql_dump - because I want to have a one-line command

# remove indentation
sed "s/^[ \t]*//" -i "$DB_DUMP_LOCATION"

# remove comments
sed '/^--/ d' -i "$DB_DUMP_LOCATION"

# remove new lines
sed ':a;N;$!ba;s/\n/ /g' -i "$DB_DUMP_LOCATION"

# remove other spaces
sed 's/  */ /g' -i "$DB_DUMP_LOCATION"

# remove firsts line spaces
sed 's/^ *//' -i "$DB_DUMP_LOCATION"

# append new line at the end (suggested by @Nicola Ferraro)
sed -e '$a\' -i "$DB_DUMP_LOCATION"

# import sql_dump
gosu postgres postgres --single "$DATABASE_NAME" < "$DB_DUMP_LOCATION";


echo "*** DATABASE CREATED! ***"

最後に:

# no postgres is running
[myserver]# psql -h 127.0.0.1 -U postgres
psql: could not connect to server: Connection refused
    Is the server running on Host "127.0.0.1" and accepting
    TCP/IP connections on port 5432?

[myserver]# docker build -t custom_psql .
[myserver]# docker run -d --name custom_psql_running -p 5432:5432 custom_psql

[myserver]# docker ps -a
CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS                    NAMES
ce4212697372        custom_psql:latest   "/docker-entrypoint.   9 minutes ago       Up 9 minutes        0.0.0.0:5432->5432/tcp   custom_psql_running

[myserver]# psql -h 127.0.0.1 -U postgres
psql (9.2.10, server 9.4.1)
WARNING: psql version 9.2, server version 9.4.
         Some psql features might not work.
Type "help" for help.

postgres=# 

# postgres is now initialized with the dump

それが役に立てば幸い!

45
damoiser

または、すべてのDDLスクリプトを含むボリュームを/docker-entrypoint-initdb.d/にマウントするだけです。 *。sh、*。sql、または* .sql.gzファイルに入れると、起動時にそれらを実行します。

例えば(スクリプトが/ tmp/my_scriptsにあると仮定します)

docker run -v /tmp/my_scripts:/docker-entrypoint-initdb.d postgres
27
darthbinamira

最初の実行中に数百万のレコードでpostgres DBを初期化する場合。

* .sqlダンプを使用したインポート

簡単なSQLダンプを実行して、dump.sqlファイルを/docker-entrypoint-initdb.d/。問題はspeedです。僕の dump.sqlスクリプトは約17MB(小さなDB-それらの1つだけに10万行がある10個のテーブル)であり、初期化には1分以上かかります(!)。ローカル開発/単体テストなどでは受け入れられません。

バイナリダンプを使用したインポート

解決策は、バイナリpostgresダンプを作成し、 シェルスクリプト初期化サポート を使用することです。次に、同じDBが500msのように初期化されます1分ではなく:)

1. dump.pgdata「my-db」という名前のDBのバイナリダンプ

コンテナ内またはローカルDBから直接

pg_dump -U postgres --format custom my-db > "dump.pgdata"

または、実行中のコンテナのホストから(postgres-container

docker exec postgres-container pg_dump -U postgres --format custom my-db > "dump.pgdata"

2.指定されたダンプおよび初期化スクリプトを使用してdockerイメージを作成します

$ tree
.
├── Dockerfile
└── docker-entrypoint-initdb.d
    ├── 01-restore.sh
    ├── 02-updates.sql
    └── dump.pgdata
$ cat Dockerfile
FROM postgres:11

COPY ./docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/
$ cat docker-entrypoint-initdb.d/01-restore.sh
#!/bin/bash

file="/docker-entrypoint-initdb.d/dump.pgdata"
dbname=my-db

echo "Restoring DB using $file"
pg_restore -U postgres --dbname=$dbname --verbose --single-transaction < "$file" || exit 1
$ cat docker-entrypoint-initdb.d/02-updates.sql
-- some updates on your DB, for example for next application version
-- this file will be executed on DB during next release
UPDATE ... ;

3.イメージをビルドして実行する

$ docker build -t db-test-img .
$ docker run -it --rm --name db-test db-test-img
15
Petr Újezdský

tils Flocker :という別のオプションが利用可能です。

Flockerは、PostgreSQLなどのデータベースを本番環境のコンテナで簡単に実行できるように設計されたコンテナデータボリュームマネージャです。本番環境でデータベースを実行する場合、ホスト障害からの回復などを考慮する必要があります。 Flockerは、実稼働環境にあるようなマシンのクラスター全体でデータボリュームを管理するためのツールを提供します。たとえば、サーバーの障害に応じてPostgresコンテナがホスト間でスケジュールされると、Flockerは関連するデータボリュームをホスト間で同時に自動的に移動できます。これは、Postgresコンテナーが新しいホストで起動すると、そのデータを保持することを意味します。この操作は、Flocker APIまたはCLIを使用して手動で、またはFlockerがDocker Swarm、Kubernetes、Mesosなどと統合されているコンテナオーケストレーションツールによって自動的に実行できます。

1
Max Desiatov

私は@damoiserと同じ解決策に従っていましたが、異なる唯一の状況は、すべてのダンプデータをインポートすることでした。

以下の解決策に従ってください(私は何のチェックも行っていません)

Dockerfile

FROM postgres:9.5

RUN mkdir -p /tmp/psql_data/

COPY db/structure.sql /tmp/psql_data/
COPY scripts/init_docker_postgres.sh /docker-entrypoint-initdb.d/

その後、doker-entrypoint-initdb.dスクリプト

#!/bin/bash

DB_DUMP_LOCATION="/tmp/psql_data/structure.sql"

echo "*** CREATING DATABASE ***"

psql -U postgres < "$DB_DUMP_LOCATION";

echo "*** DATABASE CREATED! ***"

そして、次のようにイメージを構築できます

docker build -t abhije***/postgres-data .

docker run -d abhije***/postgres-data 
0
Abhijeet Kamble

Dockerファイルのrunコマンドを/etc/init.d/postgresqlで事前に保留することにより、データをロードできました。私のdockerファイルには、次の行があります。

RUN /etc/init.d/postgresql start && /usr/bin/psql -a < /tmp/dump.sql
0
acknapp