PostgreSQLのバックアップ(pg_dump)#
Note
この記事は執筆途中です。
Note
この記事はpg_dumpのすべてを網羅した情報を記入する物ではなく、部内システムで利用されている用途のドキュメンテーションを目的とした内容になっています。
部内で使われている構文#
pg_dump -U db_user -F p db_name > db_dump_file.sql
-Uでデータベースの処理ユーザを指定し、-Fでフォーマットをplain text (pに)指定しています。 db_nameにはバックアップを取りたいデータベースを指定します。
この構文は実際にはDocker Composeを利用し実行されます。 例えば、Mattermostの場合、以下のような構文になります。
docker-compose exec -T postgres pg_dump -U mattermost_db_user -F p mattermost_db > db_dump_file.sql
docker-composeでは、execでコンテナ内でコマンドを実行できます。 Crontab等で実行できるようにするため、-Tを指定し、tty(標準入力など)を利用しないようにしています。
Docker ComposeのExecコマンドの処理は下記の通り行われます。
- Bashが実行する範囲を指定- この場合は、docker-compose exec -T postgres pg_dump -U mattermost_db_user -F p mattermost_dbをひとまず実行
 
- この場合は、
- docker-compose execコマンドで識別できないオプション以降を抽出- この場合は、pg_dump以降
- docker-compose exec -T postgresまではDocker Compose側で処理される
 
- この場合は、
- 抽出したコマンドをpostgresコンテナで実行- docker-compose.yamlの- serviceで指定されたコンテナ名と紐づけられる
 
- pg_dumpコマンドが引数を処理し、バックアップを作成- この場合は、-U mattermost_db_user -F p mattermost_dbが引数となる
- [重要] 出力は標準出力(一般的なターミナル)に出力される
 
- この場合は、
- 出力をファイルにリダイレクト- >で標準出力をファイルにリダイレクトする
- この場合は、db_dump_file.sqlにリダイレクトされる
- >が1つのみなので、ファイルが既に存在した場合は上書きされる(前のバックアップが残らない原因になる)
 
DockerイメージのPostgreSQLの場合、envで指定したユーザ名を-Uで指定することで、パスワード入力が必要なくなります。
Cronを使った自動バックアップの仕組み#
Cronを使った自動バックアップの仕組みは、上記の構文をCronに登録することで実現できます。
Pim内部では次のような構文を利用しています。
Important
ここで紹介されているcrontabは実環境を確認しておらず、机上の空論である可能性があります。
32 12 * * * cd /path/do/docker/compose/dir; docker-compose exec -T postgres pg_dump -U mattermost_db_user -F p mattermost_db | tee /path/to/db/backup/dir/$(date -d"-0 days" +%Y%m%d).sql | head
ここでteeとheadを使っています(これらはStep 1の段階でBashに後で実行になるため、docker内で実行されず、結果を元にホストで実行されます)
なぜteeとheadを使うかというと、pg_dumpは標準出力に出力するため、そのままリダイレクトすると、結果を確認できません。
正常にバックアップが取れていることを確認するため、最初の10行を出力してメールでレポートを送らせ、エラーとなっていないことを確認します。 pg_dumpでMattermostのDBを落とした場合、最初の10行にセキュアな情報は入らないため、このような手法を取れます。
DB Connection StringからバックアップすべきDBとそのユーザを取得する#
pg_dumpを実行するためには、DBのユーザ名とDB名・パスワードが必要です。
Ubuntu等に直接インストールされたPostgreSQL等であれば、 sudo -u postgresでコマンドを始めることで、 postgresユーザで特権的にアクセスするため、DB名のみが必要な状態になりますが、 特権的に接続できないDBで、接続情報が分からない・新たに払い出されない場合、 よく使われるConnection Stringから情報を取得する事ができます。
Tip
sudo -u postgresを利用する場合、この構文はdocker-compose execと同じ意味を持ちます。
sudo -u postgres pg_dump -F p mattermost_db > db_dump.sqlを実行した場合、 pg_dump -F p mattermost_dbをsudoコマンドがpostgresユーザ(PostgreSQLに対しての事実上の特権ユーザ)として実行し、 その結果を> db_dump.sqlの部分で、ファイルにリダイレクトするような命令になります。
以下は、Mattermostで使われているConnection Stringです。
postgres://mm_db_user:mm_db_password@db_host/db_name?sslmode=disable\u0026connect_timeout=10\u0026binary_parameters=yes
Connection Stringは多くの場合、postgres://から始まります。 これは、Connection Stringの考え方が、URLを同じであるからです。
認証情報はHTTPやHTTPSでBASICを利用する際に指定する値と同じような指定をします。
@で認証情報とホスト名を分け、:でユーザ名とパスワードを分けます。 そのため、postgres://と@までの間がユーザ名とパスワードを保持しています。 :で別けるため、mm_db_userがユーザであり、mm_db_passwordがパスワードです。
ホスト名は/までの文字列になります。 この場合、db_hostがホスト名になります。
Tip
Docker Composeの場合、Service名をホスト名として利用できます。
/以降の文字列はDB名になります。 多くの場合、ここで終わりますが、その後、?から始まるクエリパラメータが続く場合もあります。 例の場合はクエリパラメータが含まれているため、db_nameまでをDB名として利用します。
よって、上記のConnection Stringからは、次の情報が取得できます。
- ユーザ名: mm_db_user
- パスワード: mm_db_password
- ホスト名: db_host
- DB名: db_name