LoginSignup
10
2

More than 1 year has passed since last update.

Cloud RunのDBマイグレーションどうする問題にCloud Runジョブで対処する

Last updated at Posted at 2022-12-03

RailsアプリをCloud Runで動かすときにいくつか悩むことがありますが、そのひとつにDBマイグレーションをどうやって実行するかがあると思います。
この問題の解決策としてCloud Runジョブを使ったらうまくはまったのでご紹介します。

おことわり

Cloud Run自体の説明やCloud Runへのデプロイ方法については省略しています。別途公式ドキュメントや解説記事を参照してください。

また、Cloud Runジョブは現在プレビューとして提供されているので、事前に利用規約などをご確認ください。

Cloud RunのDBマイグレーションどうする問題とは

RailsアプリのDBマイグレーションはrails db:migrateコマンドの実行によって行います。

Cloud RunにデプロイしたRailsアプリでrails db:migrateを実行したいと思っても、Cloud Runサービスはリクエストを受けて処理を実行するものなので、リクエストを伴わずに特定の処理を実行させることはできません。

コンテナ起動処理に混ぜ込んだりCloud Runの外で実行したりいくつか方法はありますが、今回はCloud Runジョブを使う方法を順を追って設定していきます。

事前準備: Cloud RunにRailsアプリをデプロイ

サンプルとして単純なRailsアプリを用意しました。

Cloud SQLのMySQLインスタンスに接続するので、Cloud SQLのインスタンスとデータベースを作成しておきます。

まずは普通にRailsアプリをデプロイしてブラウザでアクセスできることを確認します。

image.png

Cloud Runジョブでrailsコマンドを実行してみる

Cloud Runジョブの動作確認として、rails aboutコマンドをCloud Runジョブで実行してみます。

Cloud Runジョブは現在プレビューでbetaコンポーネントのインストールが必要なので、まだインストールしていなければインストールしておきます。

gcloud components install beta

ジョブを作成します。

gcloud beta run jobs create rails-about \
    --image [イメージURL] \
    --command bin/rails \
    --args about \
    --parallelism 1 \
    --max-retries 0 \
    --execute-now  \
    --wait

オプションの意味は次のとおりです。

  • --command, --args
    • 実行するコマンドとコマンドの引数
  • --parallelism 1
    • 並列実行してほしくないので1を指定
  • --max-retries 0
    • コマンドがエラーになったらリトライせずにそのまま終了
  • --execute-now
    • ジョブ作成後すぐ実行
  • --wait
    • ジョブの完了を待つ

ジョブが完了したら、GCPコンソールでジョブの実行結果を確認します。

image.png

rails aboutのコマンド結果が確認できました。

Cloud Runジョブでrails db:migrateを実行する

Cloud Runジョブでrailsコマンドを実行できることが確認できたので、次はrails db:migrateを実行してみます。

ジョブを実行する前に、DBマイグレーションされていないのを確認してみます。
/postsにアクセスするとエラーになります。ログを見るとpostsテーブルが存在していないことがわかります。

image.png

ではジョブを作成します。

gcloud beta run jobs create rails-db-migrate \
    --image [イメージURL] \
    --command bin/rails \
    --args db:migrate \
    --set-cloudsql-instances [インスタンス接続名] \
    --set-env-vars DATABASE_USERNAME [DBユーザー名] \
    --set-env-vars DATABASE_PASSWORD [DBパスワード] \
    --set-env-vars DATABASE_SOCKET /cloudsql/[インスタンス接続名] \
    --parallelism 1 \
    --max-retries 0 \
    --execute-now  \
    --wait

--argsdb:migrateを指定します。
--set-cloudsql-instances--set-env-varsはCloud Runサービスと同じ情報を指定すればOKです。

先ほどと同じようにGCPコンソールでジョブの実行結果を確認します。

image.png

再度/postsにアクセスすると今度は正常にページが表示されました。

image.png

デプロイフローに組み込む

最後に、CI/CDのデプロイフローに組み込むことを考えます。

既存のデプロイフローにコンテナイメージのビルドとCloud Runサービスのデプロイがあると思うので、その間にジョブの実行を挟みます。

gcloud beta run jobs update rails-db-migrate \
    --service-account [サービスアカウントID] \
    --image [イメージURL] \
    --command bin/rails \
    --args db:migrate \
    --set-cloudsql-instances [インスタンス接続名] \
    --set-env-vars DATABASE_USERNAME=[DBユーザー名] \
    --set-env-vars DATABASE_PASSWORD=[DBパスワード] \
    --set-env-vars DATABASE_SOCKET=/cloudsql/[インスタンス接続名] \
    --parallelism 1 \
    --max-retries 0 \
    --execute-now \
    --wait

ビルドした最新のコンテナイメージを使うようにgcloud beta run jobs updateでジョブ定義を更新します。
--service-accountでデプロイフローで使用してるサービスアカウントの権限でジョブ実行するように指定します。

まとめ

Cloud Runに載せたRailsアプリのDBマイグレーションをCloud Runジョブで実行してみました。
業務で運用しているRailsアプリでこの方法を導入していまのところ安定してデプロイできています。

いままでCloud RunではrailsコマンドやRakeタスクを実行するのが面倒でしたが、Cloud Runジョブの登場で弱点がひとつ消えてまた便利になりました。

10
2
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
10
2