docker-compose で PostgreSQL のストリーミングレプリケーションをサクッと試す

PostgreSQL のレプリケーションははるか昔に pgpool (pgpool-II ではなく) でレプリケーションさせて以来まったく触ってなかったので、組み込みのストリーミングレプリケーションをサクッと試してみました。

他にも色々パラメータを調整すべきものがあるらいしのだけど、とりあえずそれっぽく動いているところまで。

docker-compose で MySQL レプリケーション環境をサクッと用意する でやったように /docker-entrypoint-initdb.d/*.sh を使って docker-compose up だけでできるとよいかと思ったのだけど面倒だったので泥臭く構築。

docker-compose.yml は次の通り。

version: '3.7'

services:

  master:
    image: postgres:11-alpine
    ports:
      - 15432:5432
    environment:
      POSTGRES_DB: test
    volumes:
      - master:/var/lib/postgresql/data

  slave:
    image: postgres:11-alpine
    ports:
      - 25432:5432
    environment:
      POSTGRES_DB: test
    volumes:
      - slave:/var/lib/postgresql/data

volumes:
  master:
  slave:

次のように構築&動作確認。

# master のデータベースディレクトリを初期化
# リッスン開始した風のログが表示されたところで Ctrl+C で止める
docker-compose run --rm master

# pg_hba.conf を見てみる
docker-compose run --rm master cat /var/lib/postgresql/data/pg_hba.conf

# `host all all all trust` があるのだけどこれだけではレプリケーションはできないものなの?(よくわからない)
# ので追記
echo "host replication all all trust" | docker-compose run -T --rm master tee -a /var/lib/postgresql/data/pg_hba.conf

# master を開始する
docker-compose up -d master

# レプリケーションユーザーの作成
echo 'CREATE ROLE repl_user LOGIN REPLICATION' | psql -h127.0.0.1 -p15432 -Upostgres

# slave で master から pg_basebackup してデータディレクトリを初期化
docker-compose run --rm slave pg_basebackup -h master -D /var/lib/postgresql/data -R --progress -U repl_user

# slave も開始
docker-compose up -d

# master に接続してレプリケーションの状態を見たりテーブルを作ってデータを入れたりする
psql -h127.0.0.1 -p15432 -Upostgres test
  SELECT * FROM pg_stat_replication;
  create table t (id int not null primary key, name text not null);
  insert into t values (1, 'ore');
  insert into t values (2, 'are');
  insert into t values (3, 'sore');

# slave に接続してレプリケーションされたデータを見たりデータを入れようとしてみる
psql -h127.0.0.1 -p25432 -Upostgres test
  select * from t;
  insert into t values (4, 'dore');
  #=> ERROR:  cannot execute INSERT in a read-only transaction

参考