0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【怨霊】pg_dump: error: aborting because of server version mismatchが憎い

Posted at

趣旨

pg_dump: error: aborting because of server version mismatchが憎い。ただそれだけ。

ローカル環境で建てたPostgreSQLをクラウドに移行したい。あるいはスキーマをSQLで取得したい。
本当はローカルで

pg_dump -d {DB_NAME} -h localhost -p {PORT} -U {DB_USER} > db.dump

をしたい。サクッとダンプファイルを取って、あとはpg_restoreして終わりにしたい。

だがそういう時に限って

pg_dump: error: server version: xx.yy; pg_dump version: xx.zz (Homebrew)
pg_dump: error: aborting because of server version mismatch

とエラーが出る。その都度対応するバージョンのPostgreSQLを入れて、パスを指定して実行している。

ええい、私を煩わせないでくれ。

JUST DO IT!

要点1. 使いたいバージョンのPostgreSQLが入ったDocker Containerをたてる。
要点2. ローカルCLIからContainerのCLIに接続する。Container環境でpg_dumpを使う。
要点3. pg_dumpの結果を、ローカルにマウントされた領域へ保存し、共有する。

手順

1. Dockerで接続先のPostgreSQLと同じバージョンを用意する

まず、接続先のPostgreSQLのバージョンを確認しよう。接続できるなら、以下のコマンドで確認できる。

psql -h {HOST} -p {PORT} -U {DB_USER} -d {DB_NAME} -c "SELECT version();"

バージョンが PostgreSQL 16.2 なら、Docker Hubから postgres:16 のイメージを使えばいい。マイナーバージョンまで厳密に合わせる必要はない。メジャーバージョンが合っていればpg_dumpは動く。

2. docker-compose.ymlを作る

プロジェクトのルートにdocker-compose.ymlを作成する。ポイントは2つ。

  1. ボリュームマウント: ダンプファイルを保存するディレクトリをマウントする
  2. ネットワーク: ローカルのPostgreSQLに接続できるようにする
version: '3.8'

services:
  pg-dump-tool:
    image: postgres:16  # ここを接続先のバージョンに合わせる
    container_name: pg-dump-helper
    volumes:
      - ./dumps:/dumps  # ダンプファイルの保存先
    environment:
      - POSTGRES_PASSWORD=dummy  # 使わないけど必須
    network_mode: "host"  # ローカルのPostgreSQLに接続するため
    command: sleep infinity  # コンテナを起動したままにする

network_mode: "host" がミソ。これで、コンテナ内から localhost で、ローカルのPostgreSQLに接続できる。

3. コンテナを起動する

docker-compose up -d

コンテナが起動したか確認。

docker ps | grep pg-dump-helper

4. コンテナ内で pg_dump を実行する

いよいよ本番。コンテナの中に入って、pg_dumpを実行する。

docker exec -it pg-dump-helper bash

コンテナ内のシェルに入ったら、以下を実行。

pg_dump -h localhost -p 5432 -U {DB_USER} -d {DB_NAME} -F c -f /dumps/db.dump
  • -F c: カスタム形式(バイナリ)でダンプ。pg_restoreで使いやすい
  • -f /dumps/db.dump: 保存先。マウントした /dumps に保存する

パスワードを聞かれるので入力する。

もしスキーマだけ欲しいなら --schema-only を追加。

pg_dump -h localhost -p 5432 -U {DB_USER} -d {DB_NAME} --schema-only > /dumps/schema.sql

完了したら exit でコンテナから抜ける。

5. ローカルでファイルを確認

プロジェクトルートの dumps/ ディレクトリに、ダンプファイルが保存されているはず。

ls -lh dumps/

あとはこれを pg_restore なり psql なりで好きに使えばいい。

# カスタム形式の場合
pg_restore -h {NEW_HOST} -p {PORT} -U {DB_USER} -d {DB_NAME} dumps/db.dump

# SQLファイルの場合
psql -h {NEW_HOST} -p {PORT} -U {DB_USER} -d {DB_NAME} < dumps/schema.sql

6. 後片付け(任意)

終わったらコンテナを止めて削除。

docker-compose down

次に使うときは、また docker-compose up -d すればいい。バージョンを変えたければ、docker-compose.ymlimage を書き換えるだけ。

まとめ

バージョンミスマッチで詰まったら、こうすればいい。

  1. 接続先のPostgreSQLバージョンを確認
  2. 同じバージョンのDockerイメージを用意
  3. ボリュームマウントして、コンテナ内でpg_dump
  4. ローカルにファイルが残る

Homebrewで複数バージョンのPostgreSQLを管理するより、よっぽど楽。Dockerさえ入っていれば、どのバージョンでもすぐに使える。

そもそもPostgreSQLのインスタンスをDocker Containerで立てて、docker exec -itで環境に入りpg_dumpを実行すれば良いだけの話でもある。

そのあたりは状況に応じて使い分ければ良いか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?