postgresイメージは使わずにDockerでPostgreSQLに初期データを投入

はじめに

公式のイメージは使いません。
CentOS7イメージベースでPostgreSQLをインストールしたかったので、DBに初期データを投入する方法を確認しました。
紹介する仕組み自体はCentOSに依存するものではないので他のディストリビューションでも流用できると思います。
実装にあたっては一部公式イメージを参考にさせてもらいました。

実装

CentOS7イメージベースでPostgreSQL12をインストールします。
初期設定用のスクリプト entrypoint.shENTRYPOINT に、 初期データの投入後に実行するコマンド postgresCMD に指定してます。

entrypoint.sh ではコンテナ起動時( docker run )に $PGDATA が空であれば次の処理を実行します。

  • データベースクラスタの作成( initdb
  • データを投入するためにサーバを起動( pg_ctl -w start
  • /init/ にコピーしておいた setup.sql を実行( psql -f
  • サーバを停止( pg_ctl -w stop

pg_ctl-w オプションを指定しないとサーバ起動前にSQLを実行しようとしてしまうので注意です。

最後に、 exec コマンドで引数( CMD )を実行します。

setup.sql にはDBに初期データを投入するSQLを記述します。
以下の例ではデータベース your_db にテーブル your_table を作成し、適当な行を3件挿入してます。

動作確認

コンテナイメージのビルド

イメージのタグは centos7-pg12 とします。

$ ls 
Dockerfile  entrypoint.sh   setup.sql
$ docker build -t centos7-pg12 .
...
Successfully built 09c30d332bef
Successfully tagged centos7-pg12:latest

コンテナの起動

docker run によって /init/entrypoint.sh postgres が実行されます。
省略してますが、データを永続化する場合にはボリュームを設定してください。

$ docker run -itd --name centos7-pg12 centos7-pg12 
39a7f2e6b75089df8dc0cd5914f4cf4e87c9c11300093178b686dee043035449

Dockerログの確認

entrypoint.sh の実行結果を確認します。

$ docker logs -f centos7-pg12
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "C".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/pgsql/12/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    pg_ctl -D /var/lib/pgsql/12/data -l logfile start

waiting for server to start....2020-07-20 14:18:55.477 UTC [20] LOG:  starting PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
2020-07-20 14:18:55.478 UTC [20] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2020-07-20 14:18:55.478 UTC [20] LOG:  could not bind IPv6 address "::1": Cannot assign requested address
2020-07-20 14:18:55.478 UTC [20] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
2020-07-20 14:18:55.482 UTC [20] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2020-07-20 14:18:55.486 UTC [20] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2020-07-20 14:18:55.499 UTC [20] LOG:  redirecting log output to logging collector process
2020-07-20 14:18:55.499 UTC [20] HINT:  Future log output will appear in directory "log".
 done
server started
CREATE DATABASE
You are now connected to database "your_db" as user "postgres".
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
waiting for server to shut down.... done
server stopped
2020-07-20 14:18:56.126 UTC [1] LOG:  starting PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
2020-07-20 14:18:56.127 UTC [1] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2020-07-20 14:18:56.127 UTC [1] LOG:  could not bind IPv6 address "::1": Cannot assign requested address
2020-07-20 14:18:56.127 UTC [1] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
2020-07-20 14:18:56.133 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2020-07-20 14:18:56.140 UTC [1] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2020-07-20 14:18:56.155 UTC [1] LOG:  redirecting log output to logging collector process
2020-07-20 14:18:56.155 UTC [1] HINT:  Future log output will appear in directory "log".

データベースの確認

your_db が作成できています。

$ docker exec centos7-pg12 psql -c "\l"
                             List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   
-----------+----------+----------+---------+-------+-----------------------
 postgres  | postgres | UTF8     | C       | C     | 
 template0 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 your_db   | postgres | UTF8     | C       | C     | 
(4 rows)

テーブルの確認

your_dbyour_table が作成されています。

$ docker exec centos7-pg12 psql your_db -c "\d"
           List of relations
 Schema |    Name    | Type  |  Owner   
--------+------------+-------+----------
 public | your_table | table | postgres
(1 row)

テーブルデータの確認

your_table に3件のデータが確認できます。

$ docker exec centos7-pg12 psql your_db -c "SELECT * FROM your_table;"
 foo 
-----
 a
 b
 c
(3 rows)