postgresコンテナのデータを永続化するにはボリューム指定するのが定石だけど、うっかりしてコンテナ再作成後にデータが消えていた場合のサルベージ方法について。
ちなみにアプリの都合でpostgres:12を使ってるけど、2024年にサポート終了してるのね。本文中はver17の情報にリンク。
なお、DBは専門じゃないので「そんなんよりこんな方法があるよ」とかあればぜひ教えてください。
データのサルベージ
まずpostgresコンテナは /var/lib/postgresql/data に VOLUME 指定してあるため、とりあえずコンテナデプロイ時にボリューム指定していなくてもデータが暗黙的にボリューム保存される。
よって、コンテナデプロイ時にうっかりしてボリューム未指定であっても、/var/lib/docker/volumes 以下を頑張って漁ればコンテナ削除後でも(ボリュームを消していなければ)データのサルベージは可能。
探し方としては ls /var/lib/docker/volumes/*/*/pg* などを実行して地道にやるしかないかな?
サルベージしたデータでバインドマウント
/var/lib/docker/volumes から掘り起こしたDBのデータをどこか適当な場所へコピーし、コンテナから /var/lib/postgresql/data で参照できるような定義でpostgresをデプロイする。
compose.yamlのある場所から見て ./volume/data 以下にデータがある構成なら以下のとおり。
volumes: - $PWD/volume/data:/var/lib/postgresql/data
これで先ずはバインドマウントした状態でDBがデプロイされる。
ちなみにファイルのownerはコンテナ起動時にあるべき状態に再セットされるため、あまり気にしないで良い(っぽい)
DBバックアップ
バインドマウントしたDB領域で無事に起動したら、このデータを pg_dumpall でバックアップする。
その際、ホストOSからdocker execで実行、結果をファイルへリダイレクトすればホストOS上にバックアップデータが生成される。
$ docker compose exec db pg_dumpall -U r-board > dumpfile.sql $ ls compose.yaml dumpfile.sql volume
データを吸い出せたら、一度コンテナを停止(削除)する。
ボリュームマウントで起動
ボリュームマウントする定義に変更してDBコンテナをデプロイ。 composeの場合は(アプリの初回起動時に初期データ構築等が行われるなら)DBのみをデプロイ。
services: db: image: postgres:12 environment: POSTGRES_USER: r-board POSTGRES_PASSWORD: パスワード [snip] volumes: - pg_data:/var/lib/postgresql/data volumes: pg_data:
docker compose up -d db
もちろん新規ボリュームになるため、(ユーザー名指定による最低限の初期状態の生成データを除いて)中身は空。
$ docker compose exec db bash root@c395a389f69c:/# psql -U r-board psql (12.22 (Debian 12.22-1.pgdg120+1)) Type "help" for help. r-board# \dt Did not find any relations.
バックアップデータをリストア
pg_dumpall で取得したデータを psql コマンドで流し込む。
cat dumpfile.sql | docker compose exec -T db psql -U ユーザー名
これでデータが復元される。(データによってはコンテナ起動時に作られるためalready existsになると思うが基本問題ない)
$ docker compose exec db bash
root@c395a389f69c:/# psql -U r-board
psql (12.22 (Debian 12.22-1.pgdg120+1))
Type "help" for help.
r-board=# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+---------
public | app_user | table | r-board
public | board | table | r-board
public | board_access | table | r-board
public | board_api_token | table | r-board
public | board_event | table | r-board
public | pgmigrations | table | r-board
public | user_board | table | r-board
(7 rows)
r-board=#
アプリケーション(というかDB以外)のコンテナをデプロイ
数が少なければ個別にデプロイする…でもいいが、composeを使っていればdocker compose up -dすれば未起動のコンテナはすべて起動する。
これで、ボリューム領域にリストアされたデータでDBが使用可能状態になる。
環境
$ docker --version Docker version 28.3.3, build 980b856 $ docker compose exec db psql --version psql (PostgreSQL) 12.22 (Debian 12.22-1.pgdg120+1)
システム的には以下のアプリで使用しているデータベース