🤖

Docker上のPostgreSQLをバックアップ・リストア方式でアップグレードする

2022/10/28に公開約3,100字

PostgreSQLがローカルマシンに直接インストールされている場合、pg_upgrade を実行すれば良いのですが、Dockerで動いているPostgreSQLをアップグレードする方法に迷いました。手順を本稿にメモしておきます。

TL;DR

Webの翻訳支援システムである Weblate はOSSとして展開しており、コントリビューションガイドの一環で Docker上の PostgreSQL をアップグレードする記述がありました。今回はこちらを拝借して自分の環境で試したので、同じ手順です。

https://docs.weblate.org/ja/latest/admin/install/docker.html#upgrading-the-docker-container

環境

ローカルマシンの環境です。

  • M1 Mac Monterey
  • Docker for Mac
  • docker compose でPostgreSQLを利用
  • PostgreSQL11 => 14へ上げたい

PostgreSQL のバージョンを変えただけでは、エラーになる

このように docker-compose.yml を変えますが...

docker-compose.yml
version: "3"

volumes:
  db-data:

services:
  db:
-   image: postgres:11
+   image: postgres:14
    container_name: db
    volumes:
      - db-data:/var/lib/postgresql/db_development/data
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password

互換性がないので起動できません。

docker compose up
db  |
db  | PostgreSQL Database directory appears to contain a database; Skipping initialization
db  |
db  | 2022-10-28 05:53:15.039 UTC [1] FATAL:  database files are incompatible with server
db  | 2022-10-28 05:53:15.039 UTC [1] DETAIL:  The data directory was initialized by PostgreSQL version 11, which is not compatible with this version 14.0 
db exited with code 1

いくつか選択肢がある

DockerのPostgreSQLバージョンをあげるには、いくつか選択肢があります。

  1. これまでのデータをあきらめて、ボリュームとコンテナを再作成する
  2. 有志による docker-postgres-upgrade を使う
  3. バックアップ・アップグレード・リストアの順で実行する(本稿)

1は、ローカル開発ならありえる選択肢です。すべてのデータがseedなどで再作成できるならば、確実な方法です。2は、素敵なツールが公開されているのですが、実行したときに

could not open version file "/var/lib/postgresql/11/data/PG_VERSION": No such file or directory

のように言われてしまい、結局そこで終わっています。少しチューニングすれば実行できるのかもしれませんが、あきらめました。以降は3について述べます。

バックアップ・アップグレード・リストアの手順

Weblateのコントリビューションガイドを参考にしています。なお、ユーザー名などは、

設定名 設定値
ユーザー名 postgres
パスワード password

以上の前提で進めます。

DBバックアップ

古いバージョンのPostgreSQL(今回は11)で実行します。

# まず起動
docker compose up -d

# バックアップをとる
docker-compose exec db pg_dumpall --clean --username postgres > backup.sql

# データベース コンテナの停止:
docker compose stop

ボリュームを削除

docker-compose rm -v db

docker volume ls # 削除するボリューム名を特定
docker volume remove app_db-data

アップグレード

新しい PostgreSQL のバージョンを使用するように :file:docker-compose.ymlを編集します。

docker-compose.yml
version: "3"

volumes:
  db-data:

services:
  db:
-   image: postgres:11
+   image: postgres:14
    container_name: db
...(後略)

docker-compose.yml を編集した状態で起動します。

docker compose up -d

# バックアップファイルからリストア
cat backup.sql | docker-compose exec -T db psql --username postgres

パスワードを再設定

PostgreSQL11から14へアップグレードする場合、パスワードのハッシュ化アルゴリズムが変わっているため、再設定します。

docker exec -it app_db bash
> su postgres
> psql
> \password postgres;
Enter new password for user "postgres":
==> password <Enter>

これでアプリやSQLクライアントから接続できるようになるはずです。

Discussion

ログインするとコメントできます