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?

More than 1 year has passed since last update.

RailsでPostgreSQLのバックアップファイルを作成する

Posted at

ステージング環境データベースのバックアップを取得してローカル環境に流したいということがあり本題のことをやるに至りました。

利用技術のバージョンは以下です。今回DBはPostgreSQLに限りたいと思います

技術名称 バージョン
Ruby 3.2.2
Rails 7.0.4.3
PostgreSQL 14.6

全体の流れ

  1. 環境構築(今回Railsを動かしているイメージにpostgresql-client-14が単純には入らなかったのでその解説)
  2. バックアップファイルの作成
  3. バックアップしたファイルをS3にアップロード

といった流れで行います。

1. 環境構築

PostgreSQLでバックアップファイルを作成するために pg_dumpコマンドを利用します。

Dockerコンテナ内で開発を行っている場合には、DBのコンテナとRailsのコンテナが異なっており、Railsコンテナにはpostgresql-clientがなく、pg_dumpコマンドを利用できないといったことがあるかも知れません。

pg_dumpコマンドがすでに利用できる環境の方は、この章を飛ばしていただいて構いません。ぜひ次の章へ バックアップファイルを作成

postgresql-clientのインストール

pg_dumpコマンドを使える様にするために、RailsのDockerfileのapt installを実行している箇所に、以下のようにpostgresql-clientを追加します。

RUN apt update -qq && \
    apt install -y build-essential vim libvips locales tzdata \
    postgresql-client-14 #←これ追加

注意点としては、必ず実際に利用している PostgreSQLのバージョンに合わせたバージョンをインストールしてください。
バージョンが異なる場合には、pg_dumpができない場合があります。

しかし、2023年4月時点では、PostgreSQLの14系をインストールするには、1つ工夫が必要です。
上記の様にpostgresql-client-14を追加するだけでは、「14系が見つからない」というエラーが発生してインストールができません。

postgresql-client-14をインストールするために

結論apt install -y postgresql-client-14をする前に以下の4行ほど追加しておきます。

FROM ruby:3.2.2 AS base
# ...この辺りにもみなさん数行あるだろうけど関係ないので省略

# ここから追加
RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | \
    gpg --dearmor -o /usr/share/keyrings/postgresql-keyring.gpg && \
    echo "deb [signed-by=/usr/share/keyrings/postgresql-keyring.gpg] http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | \
    tee /etc/apt/sources.list.d/postgresql.list
# 追加はここまで

RUN apt update -qq && \
    apt install -y build-essential vim libvips locales tzdata \
    postgresql-client-14

追加した4行についてざっくり解説します。
1行目は、curlコマンドでhttpリクエスト送信してPostgreSQLリポジトリの公開鍵をダウンロードしています。
2行目は、gpgコマンドで先にダウンロードした鍵をデコードして/usr/share/keyrings/postgresql-keyring.gpgファイルに保存しています。
3,4行目は、PostgreSQLパッケージのAPTリポジトリをechoで出力して、その出力をteeコマンドで /etc/apt/sources.list.d/postgresql.listファイルに書き込んでいます。

参考: https://linuxways.net/debian/how-to-install-postgresql-14-on-debian-11/

これでpg_dumpコマンドに必要なpostgresql-clientのインストールができたかと思います。

バックアップファイルの作成

今回、バックアップの処理はサービスクラスで行う様にしました。
これは私がRakeタスクでバックアップ取りたいと思い、「Rakeタスクからは対応するサービスクラスを呼び出すだけに留める」という方針で開発しているため、サービスクラスに書いております。

全体のコードをとりあえず載せておきます。長いので折りたたみ式です。

全体のコード
class Tasks::Tools::DbBackupService
  def initialize
    @filename = "backup.sql"
  end

  def execute
    backup
    upload
    Rails.logger.debug `rm -f tmp/#{@filename}`
    ServiceResponse.success(message: "バックアップが完了しました")
  end

  private

  def backup
    db_config = Rails.configuration.database_configuration[Rails.env]

    cmd = `PGPASSWORD="#{db_config["password"]}" \
            pg_dump -F p -v \
            -U #{db_config["username"]} \
            -h #{db_config["host"]} \
            -d #{db_config["database"]} \
            -p #{db_config["port"]} \
            -f tmp/#{@filename}`
  end

  def upload
    s3_client.put_object(
      bucket: Rails.application.credentials.aws[:s3_user][:bucket],
      body: File.open("tmp/#{@filename}"),
      key: @filename
    )
  end

  def s3_client
    Aws::S3::Client.new(
      region: Rails.application.credentials.aws[:s3_user][:region],
      credentials: Aws::Credentials.new(
        Rails.application.credentials.aws[:s3_user][:access_key_id],
        Rails.application.credentials.aws[:s3_user][:secret_access_key]
      )
    )
  end
end

特に重要な箇所のbackupメソッドだけ簡単に紹介します。
まずは以下がコードです。

  def backup
    db_config = Rails.configuration.database_configuration[Rails.env]

    cmd = `PGPASSWORD="#{db_config["password"]}" \
            pg_dump -F p -v \
            -U #{db_config["username"]} \
            -h #{db_config["host"]} \
            -d #{db_config["database"]} \
            -p #{db_config["port"]} \
            -f tmp/#{@filename}`
     Rails.logger.debug cmd
  end

db_config変数には起動している環境のDB情報が入っています。
その情報を用いてpg_dumpを行います。
pg_dumpで指定しているオプションは

  • -F pで平文のSQLスクリプトファイルの出力フォーマットを指定
  • -vで、詳細なオブジェクトコメント、開始時刻、終了時刻をダンプファイルに、進行状況メッセージを標準エラーに出力させます(ログを表示したくない場合はこのオプションは利用しないのがいいかなと)
  • -fでバックアップをファイルの置き場を指定しています。
    • 今回はtmpフォルダにbackup.sqlのようなファイル名で置いています。
  • 先頭のPGPASSWORD入力を省くため、パスワードの環境変数です。値を埋め込んでいます

pg_dumpコマンドのオプションについての公式サイトはこちら
https://www.postgresql.jp/document/14/html/app-pgdump.html#PG-DUMP-OPTIONS

これでバックアップの完了です。
今はtmp/フォルダにバックアップしたファイルが設定されています。
ローカル環境であればそれでいいですが、ステージング環境などのtmpフォルダに置かれてもローカルに持ってくるのが大変なので次にS3にアップします。

バックアップしたファイルをS3にアップロード

以下のGemを利用してS3との接続をします。使用したバージョンは 1.121.0です。

gem "aws-sdk-s3"

以下でtmpフォルダあるバックアップしたファイルをアップロードしています。

  def upload
    s3_client.put_object(
      bucket: Rails.application.credentials.aws[:s3_user][:bucket],
      body: File.open("tmp/#{@filename}"),
      key: @filename
    )
  end

  def s3_client
    Aws::S3::Client.new(
      region: Rails.application.credentials.aws[:s3_user][:region],
      credentials: Aws::Credentials.new(
        Rails.application.credentials.aws[:s3_user][:access_key_id],
        Rails.application.credentials.aws[:s3_user][:secret_access_key]
      )
    )
  end

こちらはしっかりと、他人から閲覧できないS3バケットに置くようにしましょう。

また、私はアップロードが完了したら以下の様なコードで、tmpフォルダにあるバックアップファイルは削除しています。

Rails.logger.debug `rm -f tmp/#{@filename}`

tmpフォルダに置きっぱなしも危険なので消しておきましょうね。

終わりに

以上で、初めに紹介した流れの3ステップが完了です。
個人的には、今回の本題ではないですが、postgresql-client-14のインストールが大変でした。
もし詰まっている方がいたら、この記事が参考になればと思います。

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?