logo

アルパカログ

Rails 7+webpackをCloud Run+Cloud SQL構成で動かす

この記事では Ruby on Rails 7+webpack 製のアプリケーションを Cloud Run+Cloud SQL 構成で実行する方法を説明します。DB のマイグレーションとデプロイには Cloud Build を利用します。

デプロイするアプリケーションは Rails 7をwebpackを使って構成する で作成したサンプルを用います。

この記事で説明に用いるサンプルコードは下記にあります。フォークするなどしてお使いください。

cloudbuild.yaml の作成

cloudbuild.yaml ファイルを下記の内容で作成します。

_CLOUDSQL_INSTANCE には後ほど作成する Cloud SQL のインスタンス名を、 _SERVICE_NAME には作成する Cloud Run のサービス名を設定します。

steps:
  - id: "build image"
    name: "gcr.io/cloud-builders/docker"
    entrypoint: 'bash'
    args: ["-c", "docker build --build-arg MASTER_KEY=$$RAILS_KEY -t gcr.io/${PROJECT_ID}/${_SERVICE_NAME} . "]
    secretEnv: ["RAILS_KEY"]

  - id: "push image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"]

  - id: "apply migrations"
    name: "gcr.io/google-appengine/exec-wrapper"
    entrypoint: "bash"
    args:
      [
        "-c",
        "/buildstep/execute.sh -i gcr.io/${PROJECT_ID}/${_SERVICE_NAME} -s ${PROJECT_ID}:${_REGION}:${_CLOUDSQL_INSTANCE} -e RAILS_ENV=production -e RAILS_MASTER_KEY=$$RAILS_KEY -- bin/rails db:migrate"
      ]
    secretEnv: ["RAILS_KEY"]

  - id: "deploy container image to Cloud Run"
    name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: gcloud
    args:
      [
        "run",
        "deploy",
        "${_SERVICE_NAME}",
        "--image",
        "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}",
        "--region",
        "${_REGION}",
      ]

substitutions:
  _CLOUDSQL_INSTANCE: rails7
  _REGION: asia-northeast1
  _SERVICE_NAME: rails7-cloudrun-sample
  _SECRET_NAME: rails-master-key

availableSecrets:
  secretManager:
  - versionName: projects/${PROJECT_ID}/secrets/${_SECRET_NAME}/versions/latest
    env: RAILS_KEY

images:
  - "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"

Dockerfile の設定

DockerfileCMDassets:precompile を行うように下記のように編集します。

-CMD bin/rails server -b 0.0.0.0 -p ${PORT}
+CMD bin/rails assets:precompile && bin/rails server -b 0.0.0.0 -p ${PORT}
ℹ️
assets:precompile では CSS のバンドルだけでなく wepack による JS のバンドルも行われます。

データベースの設定

config/database.yml を下記の内容に編集します。 <PROJECT_ID> 部分は自身で置き換えてください。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("DB_USER") { "root" } %>
  password: <%= ENV.fetch("DB_PASSWORD") { "" } %>
  host: <%= ENV.fetch("DB_HOST") { "mysql" } %>
  port: <%= ENV.fetch("DB_PORT") { "3306" } %>
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: rails7_cloudrun_sample_development

test:
  <<: *default
  database: rails7_cloudrun_sample_test

production:
  <<: *default
  database: rails7_cloudrun_sample
  username: rails7
  password: <%= Rails.application.credentials.production[:db_password] %>
  host: localhost
  socket: /cloudsql/<PROJECT_ID>:asia-northeast1:rails7
ℹ️
Cloud SQL へは Cloud SQL Auth Proxy を使って接続します。Cloud SQL Auth Proxy はデフォルトで localhost でリッスンします。

Google Cloud プロジェクトの作成

Google Cloud コンソールを開いてプロジェクトを作成します。

ここではプロジェクトIDを rails7-cloudrun-sample としてプロジェクトを作成します。

Cloud SQL インスタンスの作成

Cloud SQL を開きインスタンスを作成します。API を有効にして rails7 というインスタンス ID でインスタンスを作成します。リージョンは東京 (asia-northeast1) を選択します。

しばらくしてインスタンスが作成できたら rails7 という名前でユーザーを作成します。

パスワードは自前で作成して登録します。下記のようにランダムな文字列を作成することができます。

% cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 24 | head -n1

次にデータベースを rails7_cloudrun_sample という名前で作成します。

画像が読み込まれない場合はページを更新してみてください。
データベースを作成する

ユーザーの作成とデータベースの作成はコンソールの左カラムにメニューがあります。

画像が読み込まれない場合はページを更新してみてください。
データベースとユーザーは左カラムにメニューがある

シークレットの作成

ターミナルに戻ってシークレットを作成します。

% docker compose run --rm -e EDITOR=vim app bin/rails credentials:edit

先ほど作成した Cloud SQL の rails7 ユーザーのパスワードを秘匿情報に保存します。

 secret_key_base: aaa
+production:
+  db_password: aaa

Secret Manager にマスターキーを登録

Google Cloud コンソールに戻り、Secret Manager を開き API を有効にしたら rails-master-key という名前で、 config/master.key の中身を値としてシークレットを作成します。

Cloud Run サービスの作成

Cloud Run を開き rails7-cloudrun-sample という名前でサービスを作成します。

まだコンテナイメージが無いので、コンテナイメージの URL は gcr.io/rails7-cloudrun-sample/rails7-cloudrun-sample として手動で登録します。

リージョンは東京 (asia-northeast1) を選択します。

画像が読み込まれない場合はページを更新してみてください。
Cloud Run サービスを作成する

「Container, Variables & Secrets, Connections, Security」メニューを展開し「変数とシークレット」タブを選択します。

環境変数として下記を設定します。

  • RAILS_ENV=production
  • RAILS_LOG_TO_STDOUT=1
  • RAILS_SERVE_STATIC_FILES=1

Secrets では Secret Manager に登録した rails-master-key を選択し「環境変数として公開」を選びます。環境変数の名前は RAILS_MASTER_KEY とします。

画像が読み込まれない場合はページを更新してみてください。
環境変数を設定する
ℹ️
RAILS_LOG_TO_STDOUT を設定するとログが標準出力に出力されログエクスプローラで確認できるようになります。RAILS_LOG_TO_STDOUT に設定する値は何でも構いません。

次に「接続」タブを開き「Cloud SQL 接続」を追加します。

先ほど作成した Cloud SQL の rails インスタンスを選択します。

画像が読み込まれない場合はページを更新してみてください。
Cloud SQL への接続を追加する

「作成」ボタンを押して Cloud Run サービスを作成します。

この時点では Docker イメージがまだ無いためデプロイに失敗しますが問題ありません。

次に Cloud Run サービス一覧で rails7-cloudrun-sample にチェックを入れ、情報タブから「プリンシパルを追加」を選択します。

「新しいプリンシパル」に allUsers を入力し、ロールには「Cloud Run 起動元」を選択して保存します。

画像が読み込まれない場合はページを更新してみてください。
allUsers を「Cloud Run 起動元」ロールで追加する。

Cloud Build トリガーの設定

これまでの変更をリポジトリに push したら Cloud Build を開き「トリガー」から deploy-rails7-cloudrun-sample という名前でトリガーを作成します。リポジトリは自身の GitHub リポジトリを選択してください。

左カラムの「設定」から「API を表示」を選び API を有効化しておきます。

権限の設定

IAM を開き PROJECTNUM@cloudbuild.gserviceaccount.comPROJECTNUM-compute@developer.gserviceaccount.com に必要な権限を付与します。

Cloud Build サービスアカウントに Cloud Build から Cloud SQL インスタンスの接続に cloud_sql_proxy を使うため 「Cloud SQL 管理者」を、Compute Engine のサービスアカウントにシークレットマネージャーからシークレットを取得するため「Secret Manager のシークレット アクセサー」を付与します。

その他は下記の画像を参考にしてください。

画像が読み込まれない場合はページを更新してみてください。

デプロイの実行

リポジトリに適当にコミットするか Cloud Build トリガーを手動実行するとデプロイが始まります。

無事にビルドとデプロイが完了したら Cloud Run サービスの詳細に URL が表示されるのでブラウザでアクセスします。「Articles」と表示されていれば成功です。

もしビルドが失敗してしまったりエラーになる場合はログエクスプローラでエラーの内容を確認しましょう。

以上です。

この記事では Ruby on Rails 7+webpack 製のアプリケーションを Cloud Run+Cloud SQL 構成で実行する方法を説明しました。