postgres Official イメージ
PostgreSQLのDockerイメージとしてオフィシャルイメージがDocker Hubで公開されている。
postgres - Official Image
このイメージでは初回起動時に初期データを投入するための仕組みが用意されている。
事前にデータが投入されたデータベースのコンテナを作成するのに便利。
docker-entrypoint-initdb.d
PostgreSQLのDockerイメージでは、/docker-entrypoint-initdb.d
に配置されたSQLファイルを自動的に実行する。
ローカルにSQLファイルを設置するディレクトリを作成しコンテナの /docker-entrypoint-initdb.d
にマウントすれば、
コンテナ起動時にSQLファイルが実行される。
使用例
SQLを配置するディレクトリを作成する
例えばpostgres/init
ディレクトリを作成する。
mkdir postgres/init
上記ディレクトリへ初期化時に実行してほしいSQLファイルを配置する。
$ cat postgres/init/01_init.sql
CREATE USER newuser WITH PASSWORD 'password';
CREATE DATABASE example;
\c example
CREATE TABLE users(
id integer,
name varchar(10)
);
GRANT ALL PRIVILEGES ON users TO newuser;
\c example
INSERT INTO users (id, name) VALUES (1, 'John');
INSERT INTO users (id, name) VALUES (2, 'Jane');
INSERT INTO users (id, name) VALUES (3, 'Bob');
ファイル名の順に実行されるので連番をつけるなどして実行順を制御する。
/docker-entrypoint-initdb.dをvolumesでマウントする
作成したpostgres/init
ディレクトリを以下のように/docker-entrypoint-initdb.d
にマウントする。
version: "3.7"
services:
db:
image: postgres:latest
ports:
- "5432:5432"
volumes:
# ローカルのpostgres/initディレクトリをコンテナの/docker-entrypoint-initdb.dにマウント
- ./postgres/init:/docker-entrypoint-initdb.d
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
起動
起動すると/docker-entrypoint-initdb.d
に配置したSQLファイルが実行され、ログが出力される。
試行錯誤中でSQLにエラーが有る場合などはログを確認すると良い。
$ docker compose up
...
db-1 | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/01_init.sql
db-1 | CREATE ROLE
db-1 | CREATE DATABASE
db-1 | You are now connected to database "example" as user "postgres".
db-1 | CREATE TABLE
db-1 | GRANT
db-1 |
db-1 |
db-1 | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/02_data.sql
db-1 | You are now connected to database "example" as user "postgres".
db-1 | INSERT 0 1
db-1 | INSERT 0 1
db-1 | INSERT 0 1
接続確認
psqlコマンドで接続してデータが投入されているか確認する。
$ psql -h localhost -U newuser -d example
Password for user newuser:
psql (14.2, server 16.1 (Debian 16.1-1.pgdg120+1))
WARNING: psql major version 14, server major version 16.
Some psql features might not work.
Type "help" for help.
example=> select * from users;
id | name
----+------
1 | John
2 | Jane
3 | Bob
(3 rows)
テーブルや投入されたデータを確認できる。
シェルスクリプトも実行できる
SQLファイルだけでなくシェルスクリプトも実行できる。
例えば用意しておいたダンプファイルをリストアする場合は以下のようにする。
pg_restore -U postgres -d example /docker-entrypoint-initdb.d/example.dump
中途半端に実行された場合は一度削除する
試行錯誤中に中途半端に実行された場合は、一度コンテナを削除してから再度起動すると良い。
docker composeを使用している場合はdown
コマンドに-v
オプションを付けるとボリュームも削除される。
$ docker compose down -v
仕組み
postgresのDockerイメージのdocker-entrypoint.sh
を見ると以下のようになっている。
docker_process_init_files() {
...
printf '\n'
local f
for f; do
case "$f" in
*.sh)
# https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
# https://github.com/docker-library/postgres/pull/452
if [ -x "$f" ]; then
printf '%s: running %s\n' "$0" "$f"
"$f"
else
printf '%s: sourcing %s\n' "$0" "$f"
. "$f"
fi
;;
*.sql) printf '%s: running %s\n' "$0" "$f"; docker_process_sql -f "$f"; printf '\n' ;;
*.sql.gz) printf '%s: running %s\n' "$0" "$f"; gunzip -c "$f" | docker_process_sql; printf '\n' ;;
*.sql.xz) printf '%s: running %s\n' "$0" "$f"; xzcat "$f" | docker_process_sql; printf '\n' ;;
*.sql.zst) printf '%s: running %s\n' "$0" "$f"; zstd -dc "$f" | docker_process_sql; printf '\n' ;;
*) printf '%s: ignoring %s\n' "$0" "$f" ;;
esac
printf '\n'
done
拡張子を見て、.sh
の場合は実行、.sql
の場合はSQLとして読み込んで実行している。
また、.sql.gz
の圧縮ファイルも展開して実行している。
呼び出し側は
_main() {
...
if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then
...
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*
...
変数DATABASE_ALREADY_EXISTS
は/var/lib/postgres/data/PG_VERSION
が存在するかどうかでセットされる変数。
初回起動時に作成されるファイルなので、2回目以降は実行されないように制御されている。
mysqlオフィシャルイメージでも同様
MySQLのDockerイメージでも同様の仕組みが用意されており、/docker-entrypoint-initdb.d
に配置したSQLファイルが実行される。