Postgresデータベースを含むDockerコンテナーがあります。公式の Postgres image を使用しています。これには、メインスレッドでサーバーを起動するCMDエントリがあります。
クエリのリッスンを開始する前に、RUN psql –U postgres postgres < /dump/dump.sql
を実行してデータベースにデータを入力します。
これがDockerでどのように可能かはわかりません。 CMDの後にRUN
コマンドを配置した場合、DockerがDockerfileの読み取りを完了したため、もちろん到達しません。しかし、CMD
の前に配置すると、psqlがプロセスとして存在する前に実行されます。
DockerでPostgresデータベースに事前入力するにはどうすればよいですか?
多くの戦いの後、私は解決策を見つけました;-)
私にとって非常に便利なコメントがここに投稿されました: 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
それが役に立てば幸い!
または、すべてのDDLスクリプトを含むボリュームを/docker-entrypoint-initdb.d/にマウントするだけです。 *。sh、*。sql、または* .sql.gzファイルに入れると、起動時にそれらを実行します。
例えば(スクリプトが/ tmp/my_scriptsにあると仮定します)
docker run -v /tmp/my_scripts:/docker-entrypoint-initdb.d postgres
簡単なSQLダンプを実行して、dump.sql
ファイルを/docker-entrypoint-initdb.d/
。問題はspeedです。僕の dump.sql
スクリプトは約17MB(小さなDB-それらの1つだけに10万行がある10個のテーブル)であり、初期化には1分以上かかります(!)。ローカル開発/単体テストなどでは受け入れられません。
解決策は、バイナリpostgresダンプを作成し、 シェルスクリプト初期化サポート を使用することです。次に、同じDBが500msのように初期化されます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"
$ 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 ... ;
$ docker build -t db-test-img .
$ docker run -it --rm --name db-test db-test-img
tils Flocker :という別のオプションが利用可能です。
Flockerは、PostgreSQLなどのデータベースを本番環境のコンテナで簡単に実行できるように設計されたコンテナデータボリュームマネージャです。本番環境でデータベースを実行する場合、ホスト障害からの回復などを考慮する必要があります。 Flockerは、実稼働環境にあるようなマシンのクラスター全体でデータボリュームを管理するためのツールを提供します。たとえば、サーバーの障害に応じてPostgresコンテナがホスト間でスケジュールされると、Flockerは関連するデータボリュームをホスト間で同時に自動的に移動できます。これは、Postgresコンテナーが新しいホストで起動すると、そのデータを保持することを意味します。この操作は、Flocker APIまたはCLIを使用して手動で、またはFlockerがDocker Swarm、Kubernetes、Mesosなどと統合されているコンテナオーケストレーションツールによって自動的に実行できます。
私は@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
Dockerファイルのrunコマンドを/etc/init.d/postgresqlで事前に保留することにより、データをロードできました。私のdockerファイルには、次の行があります。
RUN /etc/init.d/postgresql start && /usr/bin/psql -a < /tmp/dump.sql