Rails アプリを Cloud Run で動作させる

# はじめに
Rails の勉強をするために簡単なアプリを作成して動作確認をしたいと思いました。
今回はほぼ無料で使用できる Cloud run を利用して Rails を動かしてみます。
ちなみに使用しているPCはWindowsです。

## 元記事はこちら
ちょうど同じような思いでやられている方がいたので、こちらの記事をベースに動かします。

https://qiita.com/kato-hiroaki/items/b8abe200b4b653f0e655

## 前提
* Ruby 3.1.2
* Rails 7.0.4
* Google Cloud アカウント作成
* gcloud コマンドが使用できること

### Ruby インストール
1\. インストール
[RubyInstaller のダウンロードページ](https://rubyinstaller.org/downloads/) にアクセスします。


Ruby 3.1.2 の WITH DEVKIT バージョンをダウンロードします（64-bit 推奨）。
ダウンロードしたインストーラーを実行し、指示に従ってインストールします。

"Add Ruby executables to your PATH" にチェックを入れてください。
インストールが完了したら、"Run 'ridk install'" にチェックを入れて Finish をクリックします。


MSYS2 のインストールウィンドウが開いたら、Enter キーを押して基本的なインストールを完了します。

2\. インストールの確認
PowerShell を開き、以下のコマンドを実行して Ruby のインストールを確認します。
```
ruby -v
```
Ruby 3.1.2 がインストールされていることを確認してください。

3\. Rails のインストール

PowerShell を管理者として実行します。
以下のコマンドを実行して Rails 7.0.4 をインストールします：
```
gem install rails -v 7.0.4
```



インストールが完了したら、以下のコマンドで Rails のバージョンを確認します：
```
rails -v
```
Rails 7.0.4 がインストールされていることを確認してください。

4\. Node.js のインストール（Rails の JavaScript 依存関係のため）4\. Node.js のインストール（Rails の JavaScript 依存関係のため）

[Node.js の公式サイト](https://nodejs.org/en) から LTS バージョンをダウンロードしてインストールします。
インストールが完了したら、PowerShell を再起動し、以下のコマンドで Node.js のインストールを確認します。
```
node -v
npm -v
```
それぞれバージョンが表示されることを確認します。
これで Ruby 3.1.2 と Rails 7.0.4 が Windows 環境にインストールされ、使用する準備が整いました。

### Google Cloud アカウント作成手順
1\. ブラウザで https://cloud.google.com にアクセスします。ブラウザで https://cloud.google.com にアクセスします。
2\. 右上の「無料で開始」または「コンソールに移動」をクリックします。
3\. Googleアカウントでサインインします。Googleアカウントをお持ちでない場合は、新規作成してください。
4\. 国と組織の種類、支払い情報を入力します。
5\. 利用規約に同意し、「続行」をクリックします。
6\. アカウントのセットアップが完了したら、Google Cloud Consoleにリダイレクトされます。

### gcloudコマンドラインツールのインストール
#### Windows用
1\. https://cloud.google.com/sdk/docs/install にアクセスします。1\. https://cloud.google.com/sdk/docs/install にアクセスします。
2\. 「Windows」タブを選択し、インストーラーをダウンロードします。
3\. ダウンロードしたインストーラー（GoogleCloudSDKInstaller.exe）を実行します。ダウンロードしたインストーラー（GoogleCloudSDKInstaller.exe）を実行します。インストールウィザードの指示に従って進みます。
4\. 「Cloud SDK のインストール先を選択してください」で適切なディレクトリを選択します。コンポーネントの選択画面では、デフォルトのままで問題ありません。
5\. インストールが完了したら、「完了」をクリックします。

#### macOS/Linux用

1\. ターミナルを開き、以下のコマンドを実行してインストールスクリプトをダウンロードします。
```
Copycurl -O https://dl.google.com/dl/cloudsdk/channels/rapid/install_google_cloud_sdk.bash

```


2\. ダウンロードしたスクリプトを実行します。
```
Copybash install_google_cloud_sdk.bash
```

3\. プロンプトに従って、インストール先ディレクトリを選択します（デフォルトでよい場合はEnterキーを押します）。インストールが完了したら、ターミナルを再起動するか、以下のコマンドでシェルを更新します。
```
Copysource ~/.bashrc
``````
または
```
Copysource ~/.zshrc
```
### gcloudの初期化
1\. コマンドプロンプト（Windows）またはターミナル（macOS/Linux）を開き、以下のコマンドを実行してgcloudを初期化します。
```
gcloud init
```
2\. プロンプトに従って、Googleアカウントにログインし、プロジェクトを選択します。
3\. インストールが成功したことを確認するため、以下のコマンドを実行します。
```
gcloud versiongcloudバージョン
```
このコマンドがgcloudのバージョン情報を表示すれば、インストールは成功しています。

:::note info
以上で、前提条件となるアプリ、ツールの準備が整いました。
::::::::::::

## 構築
では、構築をしていきます。
流れは以下です。

1\. Rails アプリ作成
2\. Cloud Build でイメージ作成2\. Cloud Build でイメージ作成
3\. Cloud Run にデプロイ

### Rails アプリ作成
scaffoldを使用したCRUDページを作成します。
<details><summary>scaffoldとは</summary>
scaffoldは、Railsアプリケーションの開発を迅速に行うためのコード生成ツールです。単一のコマンドで、指定したリソース（例：投稿、ユーザー、製品など）に対する基本的なCRUD操作を実装するために必要な以下の要素を自動生成します。

* データベースマイグレーションファイル
* モデル
* コントローラー
* ビュー（index, show, new, edit, _form パーシャル）
* ルーティング設定
* リソースに対応するテストファイル
</details>

```
# Rails アプリ作成
$ rails new sample-app
$ cd sample-app

# scaffold でページ作成
$ bin/rails g scaffold Post title:string content:text
$ bin/rails db:migrate

# http://localhost:3000/posts でRubyのページが開くことを確認
$ bin/rails s
```
:::note alert
恐らく Mac の場合は上記で問題なくRubyのページが確認できると思いますが、Windowsの場合は以下のようなwebページが表示されるかもしれません。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880946/64ccf5ce-f4d0-ecbd-67a1-e438b7ce2942.png)
これはRails サーバーが正しく起動されていないことを示唆しています。
もし上記のようなページが表示された場合は、以下コマンドを実行してみてください。
```
ruby bin/rails server -p 3000
``````
実行結果は以下。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880946/4d6cccef-adc6-ef51-132d-4930d53bc52f.png)

webブラウザのタブに以下を入力
```
http://127.0.0.1:3000http://127.0.0.1:3000
```

以下のようなページが表示されればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880946/f6b2e8d8-540a-b647-09dc-b302ff828145.png)

### Cloud Build でイメージ作成

イメージ作成の設定ファイル Dockerfile を作成します。
```
touch Dockerfile
```

```php:Dockerfile
FROM ruby:3.1.2ルビーから:3.1.2
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
RUN bundle exec rails db:migrate
# Cloud Run はデフォルトポート8080で起動
EXPOSE 8080
CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "8080"]
```

Cloud Build の設定ファイル cloudbuild.yaml を作成します。
```
touch cloudbuild.yaml
``````

```php:cloudbuild.yaml
steps:
  # Cloud Build でビルド
  - id: "build image"
    name: "gcr.io/cloud-builders/docker"
    entrypoint: 'bash'
    args: ["-c", "docker build -t gcr.io/${PROJECT_ID}/${_SERVICE_NAME} . "]
  # Container Registry にアップロード
  - id: "push image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"]
substitutions:
  _SERVICE_NAME: sample-app-service
images:
  - "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"
```

次に、アカウントに対してアップロードに必要な権限を付与します。

1\. Google Cloud Consoleにアクセス1\.Google Cloud Consoleにアクセス
2\.「IAMと管理」→「IAM」に移動
3\. 該当のプリンシパル（アカウント）を見つけ、右端にある鉛筆マーク（編集ボタン）をクリック。以下の権限を付与して保存。
* Cloud Build サービス アカウント
* Cloud Build 編集者
* サービス アカウント ユーザー

まず対象のPROJECT_IDを以下コマンドで確認します。
```
gcloud projects list
```

対象PROJECT_IDを指定して、Container Registry にアップロードします。
```
gcloud builds submit . --project=$PROJECT_ID
``````

## Cloud Run にデプロイ## Cloud Run にデプロイ
Cloud Run にデプロイします。
```
# PROJECT_IDを指定します
gcloud config set project $PROJECT_ID

# --image は Container Registry にアップロードしたものを設定
# --allow-unauthenticated で誰でもアクセスできるようにする# --allow-unauthenticated で誰でもアクセスできるようにする
gcloud run deploy sample-app-service \
   --image gcr.io/$PROJECT_ID/sample-app-service \
   --region asia-northeast1 \
   --allow-unauthenticated

# 上記コマンドはWindowsでは改行を認識しない可能性があるため、Windowsの場合は以下のように一行で実行すること

gcloud run deploy sample-app-service --image gcr.io/$PROJECT_ID/sample-app-service --region asia-northeast1 --allow-unauthenticated

......

  ⠼ Creating Revision...
  . Routing traffic...
  ✓ Setting IAM Policy...

...

Service URL: https://sample-app-service-[xxx]-an.a.run.app



gcloud run deploy sample-app-service `

>>   --image gcr.io/tonal-asset-434006-m6/sample-app-service `

>>   --region asia-northeast1 `

>>   --allow-unauthenticated `

>>   --set-env-vars "RAILS_ENV=production,RAILS_SERVE_STATIC_FILES=true,RAILS_LOG_TO_STDOUT=true,SECRET_KEY_BASE=23b8ae5e4c2368fb98d80c9cdf5a35409f5a8d364a2248bb03dc827cd2bcb7e67936153c0d48b70b35fb57422b63795a76b2a103edb9205acc3289defac244a7" `

>>   --memory 512Mi

 rails secret

 RUN bundle exec rails assets:precompile

 docker push gcr.io/tonal-asset-434006-m6/sample-app-service

gcloud run deploy sample-app-service `

>>   --image gcr.io/tonal-asset-434006-m6/sample-app-service `

>>   --region asia-northeast1 `

>>   --allow-unauthenticated `

>>   --set-env-vars "RAILS_ENV=production,RAILS_SERVE_STATIC_FILES=true,RAILS_LOG_TO_STDOUT=true,SECRET_KEY_BASE=23b8ae5e4c2368fb98d80c9cdf5a35409f5a8d364a2248bb03dc827cd2bcb7e67936153c0d48b70b35fb57422b63795a76b2a103edb9205acc3289defac244a7" `

>>   --memory 512Mi

docker run --rm gcr.io/tonal-asset-434006-m6/sample-app-service ls -l /app/entrypoint.sh

 docker run -p 8080:8080 -e PORT=8080 -e RAILS_ENV=production -e RAILS_SERVE_STATIC_FILES=true -e RAILS_LOG_TO_STDOUT=true gcr.io/tonal-asset-434006-m6/sample-app-service

 docker run -p 8080:8080 -e PORT=8080 -e RAILS_ENV=production -e RAILS_SERVE_STATIC_FILES=true -e RAILS_LOG_TO_STDOUT=true gcr.io/tonal-asset-434006-m6/sample-app-service