【ポートフォリオ公開に最適!】Cloud RunでWebアプリケーションを無料で動かす方法

Google Cloud Platform (GCP) の Cloud Run を使って、Webアプリケーションを無料でデプロイする方法を紹介します。
未経験からエンジニアにキャリアチェンジを目指す方のポートフォリオ公開や、
小規模な個人開発のプロジェクトに最適な方法です。

今回はRuby on Railsのアプリケーションを例に解説しますが、
Dockerコンテナ化されたアプリケーションであれば、言語やフレームワーク問わずにデプロイできます。

背景

2022年8月25日にHerokuが無料プランを廃止をアナウンス、2022年11月28日に無料プランが終了しました。

https://www.heroku.com/blog/next-chapter/

ポートフォリオの公開や小規模な個人開発のプロジェクトを無料でホスティングする方法のファーストチョイスはHerokuでしたが、
Herokuの無料プランがなくなったことで、代替手段を探す必要があります。

そこでRenderなどのPaaS(Platform as a Service)を利用してみましたが、
無料で使えるものの次のような課題がありました。

  • コールドスタートで起動が遅い
  • スリープ時はRenderの画面が表示される
  • データベースが3か月で削除される
  • 管理画面に一人しかアクセスできないので、デバッグが難しい
  • 管理画面が使いづらい

Renderのメリットはアプリケーションサーバー、データベースをすべて無料で使えることです。
しかし、上記の課題があるため、無料で使えるものの使いづらさは否めません。

なるべく無料もしくは低コストで、かつ使いやすい環境を探していたところ、GCPのCloud Runにたどり着きました。

構成

GCPのCloud Runを使ったWebアプリケーションの構成は以下の通りです。

Cloud Run

Cloud Run

Cloud Runは完全にマネージドなコンテナ実行環境です。
Cloud RunでアプリケーションのDockerコンテナを実行します。
今回はRuby on Railsを例にしますが、他の言語やフレームワークでも同様に動作します。
Cloud Runは無料枠があり、月間200万リクエストまで無料で利用できます。
ポートフォリオや小規模な個人開発のプロジェクトであれば、無料枠内で十分に運用可能です。

Cloud Run上でデータベースはSQLite3を使用します。
Cloud Runはステートレスなサービスであるため、Cloud Runのインスタンスが停止すると、データは失われます。
そこでSQLite3のデータベースファイルをCloud Storageと連携してマウントすることで、データを永続化します。
Ruby on Railsのデフォルトの設定ではSQLiteはstorage以下にSQLite3のデータベースファイルを作成します。
そのためstorage以下をCloud Storageにマウントします。

コンテナレジストリ

Cloud Runでアプリケーションを実行するには、Dockerコンテナイメージを保存しておくレジストリが必要です。
GCPではArtifact Registryを使用します。
ただし、Artifact Registryは500MBまでのイメージを無料で保存できますが、
それ以上のサイズになると課金されます。
Railsだと500MBを超えてしまうことが多いので、Artifact Registryを使用した場合、
0.1円/日、1か月だと3円程度の課金が発生します。

次の場合は素直にArtifact Registryを使うことをおすすめします。

  • GCPで完結したい
  • 安く済ませたいが、無料にこだわる必要はない
  • Dockerイメージは非公開にしたい

もしGCPで完結する必要がなく、ポートフォリオなどの公開でソースコードやDockerイメージを公開しても問題ない場合は、
Docker Hubを利用することでArtifact Registryの課金を回避できます。

Cloud Storage

Cloud Runで動作させているSQLite3のデータベースファイルを永続化するために、Cloud Storageを使用します。
5GBまでのストレージ、5,000回のクラスAオペレーション、50,000回のクラスBオペレーションが無料で利用できます。
SQLite3のデータベースファイルは数MB程度、ポートフォリオや小規模な個人開発のプロジェクトであれば、無料枠内で十分に運用可能です。

https://cloud.google.com/free/docs/free-cloud-features?hl=ja#storage

Secret Manager

Cloud Runでアプリケーションを実行する際に、環境変数やシークレット情報を管理するために、Secret Managerを使用します。
今回はRuby on Railsで秘匿情報を管理するキーである、RAILS_MASTER_KEYをSecret Managerに保存します。
なおCloud RunでSecret Managerではなく、環境変数を直接設定することもできるため、利用は必須ではありませんが、推奨事項になります。

注意点

今回の構成は多くの場合、Artifact Registryを除き無料枠内で運用可能ですが、
利用状況によっては課金が発生する可能性があります。
またDocker Hubを利用する場合はイメージを公開する必要があるため、
ソースコードやDockerイメージを公開しても問題ない場合に限ります。
心配な方は課金については予算アラートを設定する、Docker HubではなくArtifact Registryを利用するなどの対策を検討してください。
予算アラートの設定については後述します。
「Artifact RegistryとDocker Hubのどっちを使ったらよいかわからない」という場合は、
3円/月ほど課金されますが、Artifact Registryを利用することをおすすめします。

全体像

では、実際にCloud RunでWebアプリケーションをデプロイする手順を説明しますが、
その前に全体の流れを把握しておきましょう。

  1. Googleアカウントの作成
  2. Google Cloudのアカウントを作成
  3. Dockerイメージの作成
  4. CloudStorageのバケットを作成
  5. Secret Managerの設定
  6. Artifact Registryの設定
  7. Cloud Runの設定

Docker Desktopのインストール

もし、まだDockerをインストールしていなければ、はじめにパソコンにDockerをインストールしましょう。
Docker Desktopをインストールすると、開発に必要なDocker Engine、Docker CLI、Docker Composeなどが一式インストールされます。

次のリンクから、使用しているパソコンに合わせてDocker Desktopをダウンロードしてインストールしてください。

https://www.docker.com/ja-jp/products/docker-desktop/

私の場合はWindowsを使用しているので、Windows版のDocker Desktopをインストールしました。
アプリケーションを起動して、左下のステータスがEngine runningになっていれば、Docker Desktopのインストールは成功です。

VSCoceのインストール

今回はVSCodeのDev Containerを使って開発を行います。
VSCodeをまだインストールしていない場合は、次のリンクからダウンロードしてインストールしてください。

https://code.visualstudio.com/

Dev Containerの拡張機能のインストール

VSCodeのDev Containerを使うために、次の拡張機能をインストールします。
Dev Containerを使うことで、Dockerさえあれば、Rubyなどをホストにインストールする必要がなく、コンテナ内で開発環境を構築できます。
VSCodeの拡張機能のマーケットプレイスから、次の拡張機能をインストールしてください。

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

rails-newコマンドのインストール

Railsの新しいプロジェクトを作成するために、rails-newコマンドをインストールします。

次のリリースページから、最新のrails-newコマンドをダウンロードしてインストールしてください。

https://github.com/rails/rails-new/releases

Macの場合は、rails-new-aarch64-apple-darwin.tar.gzをダウンロードします。
WindowsのWSL2の場合は、rails-new-x86_64-unknown-linux-gnu.tar.gzをダウンロードします。

ダウンロードしたファイルを解凍して、rails-newコマンドをパスの通ったディレクトリに移動します。

Terminal window
tar -xzf rails-new-aarch64-apple-darwin.tar.gz

解凍したらrails-newコマンドをパスの通ったディレクトリに移動します。

Terminal window
mv rails-new /usr/local/bin/

コマンドが実行できるか確認します。

Terminal window
rails-new --version

次のようにバージョンが表示されれば、rails-newコマンドのインストールは成功です。

Terminal window
rails-new 0.4.1

Ruby on Railsのプロジェクトを作成

次に、Ruby on Railsのプロジェクトを作成します。
先ほどインストールしたrails-newコマンドを使って、プロジェクトを作成します。
ターミナルを開いて、次のコマンドを実行してください。

-rオプションでRailsのバージョンを指定できます。
今回はRails 8.0.2を使用します。
sample_appはプロジェクト名です。
--devcontainerオプションをつけると、VSCodeのDev Containerで開発できるように設定されます。

Terminal window
rails-new -r 8.0.2 sample_app --devcontainer

プロジェクトはカレントディレクトリにsample_appというディレクトリが作成されます。

VSCodeでプロジェクトを開く

プロジェクトが作成できたら、VSCodeでプロジェクトを開きます。
VSCodeを起動して、先ほど作成したsample_appディレクトリを開いてください。

VSCodeを開くと、右下に「コンテナで開く」というボタンが表示されるので、クリックします。

コンテナで開く

もしくは、コマンドパレット(Ctrl + Shift + P)を開いて、「Dev Containers: Reopen in Container」を選択します。

これでVSCodeのDev Containerが起動し、コンテナ内で開発環境が構築されます。

簡単なTODOアプリケーションを作成

Railsのプロジェクトが作成出来たら、簡単なTODOアプリケーションを作成します。
データベースのCRUD操作を確認するためです。

次のコマンドを実行して、Railsのジェネレータを使って、Taskモデルを作成します。

Terminal window
rails generate scaffold Task title:string description:text completed:boolean

データベースにテーブルを作成するmigrationファイルなど、CRUD操作に必要なファイルが生成されます。
次に、データベースをマイグレーションします。

Terminal window
rails db:migrate

Routeの設定

次に、ルーティングを設定します。
config/routes.rbファイルを開いて、次のように設定します。
http://localhost:3000 にアクセスしてTaskの一覧が表示されるようにします。

config/routes.rb
Rails.application.routes.draw do
resources :tasks
root "tasks#index"
end

Railsの起動

次に、Railsを起動します。
ターミナルで次のコマンドを実行してください。

Terminal window
rails server

これで、Railsの開発サーバーが起動します。
http://localhost:3000 にアクセスすると、先ほど作成したTODOアプリケーションの一覧が表示されるはずです。

TODOの一覧

Dockerfileの確認

RailsはデフォルトでDockerfileが含まれています。
念のためsample_app以下のDockerfileを確認しておきましょう。
こちらのDockerfileでイメージを作成します。

Googleアカウントの作成

Google Cloud Platformを利用するには、Googleアカウントが必要です。
もしまだGoogleアカウントをお持ちでない場合は、次のリンクからアカウントを作成してください。

https://www.google.com/intl/ja/account/about/

すでにGoogleアカウントをお持ちの場合は、Google Cloud Platform用に新しいアカウントを作成する必要はありません。
既存のGoogleアカウントをそのまま利用できます。

Google Cloudのアカウントを作成する

Googleアカウントを作成したら、次のリンクからGoogle Cloud Platformのアカウントを作成してください。

https://cloud.google.com/free

右上の「無料で利用開始」ボタンをクリックして、アカウントを作成します。

プロジェクトの作成

Google Cloudのアカウントを作成出来たら、プロジェクトを作成します。

画面上部のプロジェクトタブをクリックすると、プロジェクトの一覧が表示されます。
プロジェクトを選択するか、「新しいプロジェクト」ボタンをクリックして新しいプロジェクトを作成します。

プロジェクトの作成

Cloud Storageのバケットを作成

次にSQLite3のデータベースファイルを永続化するために、Cloud Storageのバケットを作成します。

画面上部の検索バーに「storage」と入力して、Cloud Storageのページを開きます。

クラウドストレージ

バケットを作成ボタンをクリックして、バケットを作成します。

バケットを作成

バケットの名前を入力します。
わかりやすい名前をつけてください。
sample-app-sqliteのように、プロジェクト名やアプリケーション名を含めると良いでしょう。

データの保存場所は、今回は費用を抑えるためにロケーションタイプをRegion(単一リージョン)に設定します。
リージョンは、アプリケーションのユーザーが多い地域を選ぶと、パフォーマンスが向上します。
例えば、日本のユーザーが多い場合は、asia-northeast1(東京リージョン)を選択します。
他の設定はデフォルトのままで問題ありません。

設定が完了したら画面最下部の作成ボタンをクリックして、バケットを作成します。

バケットの作成

パブリックアクセスの防止のポップアップが表示されたら、
このバケットに対するパブリックアクセス禁止を適用するを選択して、確認ボタンをクリックします。
今回はCloud Runのアプリケーションからのみアクセスするため、パブリックアクセスは不要です。

パブリックアクセスの防止

バケットが作成されると、Cloud Storageのバケット一覧に表示されます。
後ほどCloud Runのアプリケーションからこのバケットをマウントして、SQLite3のデータベースファイルを永続化します。

バケットの作成

Secret Managerの設定

次に、Cloud Runでアプリケーションを実行する際に必要な秘匿情報を管理するために、Secret Managerを設定します。
今回はRailsの秘匿情報を一元管理できるキーである、RAILS_MASTER_KEYをSecret Managerに保存します。
他のアプリケーションの場合は、必要な秘匿情報を同様にSecret Managerに保存してください。

画面上部の検索バーに「Secret Manager」と入力して、Secret Managerのページを開きます。

secret manager

シークレットを作成ボタンをクリックして、シークレットを作成します。

secretの作成

シークレットの作成画面になります。
名前はrails_master_keyなど、わかりやすい名前をつけてください。
値にはsample_appconfig/master.keyの内容を入力します。
改行が入らないように注意してください。
それ以外はデフォルトのままで問題ありません。

secretの作成

名前と値を入力したら、画面最下部のシークレットを作成ボタンをクリックします。

他にも必要な秘匿情報があれば、同様にSecret Managerに保存してください。

サービスアカウントの設定

Cloud RunからSecret Managerにアクセスするためには、サービスアカウントに適切な権限を付与する必要があります。

画面上部の検索バーに「IAM」と入力して、IAMのページを開きます。

IAM

デフォルトのサービスアカウント(@development.gserviceaccount.com)の鉛筆アイコンをクリックして、編集画面を開きます。

IAMの設定

ロールのフィルタでsecretと入力すると、Secret Managerのシークレットアクセサーが表示されるので、これを選択します。

ロール

設定が完了したら、画面最下部の保存ボタンをクリックします。

これでCloud RunからSecret Managerにアクセスできるようになりました。

Artifact Registryの設定

次に、Cloud Runでアプリケーションを実行するためのDockerコンテナイメージを保存するために、Artifact Registryを設定します。
画面上部の検索バーに「Artifact Registry」と入力して、Artifact Registryのページを開きます。

Artifact Registry

Artifact Registry APIを有効にしていない場合は、画面上部のAPIを有効にするボタンをクリックして、APIを有効にします。

次に、リポジトリを作成ボタンをクリックして、リポジトリを作成します。

リポジトリの作成

リポジトリの作成画面になります。
リポジトリの名前を入力します。
わかりやすい名前をつけてください。
sample-appのように、プロジェクト名やアプリケーション名を含めると良いでしょう。

形式はDockerを選択します。
モードは標準を選択します。
ロケーションタイプは今回は費用を抑えるためにRegion(単一リージョン)に設定します。
リージョンはasia-northeast1(東京リージョン)を選択します。
他の設定はデフォルトのままで問題ありません。

設定が完了したら画面最下部の作成ボタンをクリックして、リポジトリを作成します。

リポジトリの作成

Dockerコンテナイメージの作成

次に、Dockerコンテナイメージを作成します。
ターミナルで次のコマンドを実行してください。
こちらのコマンドはsample_appディレクトリで実行する必要があります。
また、Dev Containerを使用しているときは、VSCodeのターミナルではなく、
ホストのターミナルで実行するように注意してください。

Terminal window
docker build -t sample_app .

Dockerコンテナイメージのタグ付け

次に、作成したDockerコンテナイメージにタグを付けます

タグはArtifact Registryのリポジトリ名と同じ名前を付けます。
Artifact Registryに作成したリポジトリの詳細画面でパスをコピーボタンをクリックして、パスをクリップボードにコピーします。

次のコマンドを実行して、Dockerコンテナイメージにタグを付けます。
<パス>の部分には、先ほどコピーしたパスを貼り付けてください。
Railsアプリケーションはappという名前でタグ付けします。
Artifact Registryにappという名前でDockerイメージをプッシュすることになります。

Terminal window
docker tag sample_app <パス>/app

Gcloud CLIのインストール

次に、Gcloud CLIをインストールします。
このCLIでDockerイメージのpushやCloud Runのデプロイを行います。

Terminal window
docker run -ti --name gcloud-config \
-v gcloud-config:/root/.docker \
gcr.io/google.com/cloudsdktool/google-cloud-cli:stable \
gcloud auth login

alt text

アカウントの選択画面が表示されたら、先ほど作成したGoogleアカウントを選択します。
Google Cloud SDKへのアクセスを許可する画面が表示されたら、許可ボタンをクリックします。

クレデンシャルが表示されるので、Copyボタンをクリックして、クリップボードにコピーします。

Sign in to the gcloud CLI

ターミナルに戻って、コピーしたクレデンシャルを貼り付けてEnterキーを押します。

Artifact Registryの認証

次に、Artifact RegistryにDockerイメージをプッシュするための認証を行います。
ポイントは、このコマンドを実行するとDockerコンテナの/root/.docker/config.jsonに認証情報が作成されるので、
そのボリュームをマウントして、永続化していることです。
また、usr/bin/docker/var/run/docker.sockをマウントすることで、Dockerコマンドを実行できるようにしています。
/usr/bin/dockerの部分はDockerのパスです。
もしDockerのパスが異なる場合は、適宜変更してください。
Dockerのパスを確認するには、次のコマンドを実行します。

Terminal window
which docker
Terminal window
docker run -it \
--volumes-from gcloud-config \
-v gcloud-config:/root/.docker \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
gcr.io/google.com/cloudsdktool/google-cloud-cli:stable \
bash -c "gcloud auth configure-docker asia-northeast1-docker.pkg.dev"

イメージのプッシュ

次に、DockerコンテナイメージをArtifact Registryにプッシュします。
次のコマンドを実行してください。
<パス>の部分には、先ほどタグ付けしたパスを貼り付けてください。

Terminal window
docker run -it \
--volumes-from gcloud-config \
-v gcloud-config:/root/.docker \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
gcr.io/google.com/cloudsdktool/google-cloud-cli:stable \
bash -c "docker push <パス>/app"

pushに成功するとArtifact RegistryのリポジトリにDockerイメージが保存されます。

イメージ

Cloud Runの設定

次に、Cloud Runの設定を行います。
画面上部の検索バーに「Cloud Run」と入力して、Cloud Runのページを開きます。

Cloud Run

サービスを作成ボタンをクリックして、サービスの作成画面を開きます。

サービスの作成

サービスの作成画面になります。

コンテナイメージのURLには、先ほどArtifact RegistryにプッシュしたDockerイメージを選択します。

Dockerイメージの後に:latestを付けると、最新のイメージが使用されるため、
毎回コンテナイメージのURLを変更する必要がなくなります。
今回は毎回最新のイメージを使用するため、:latestを付けておきます。
たとえばプロジェクト名がsample-project、リポジトリ名がsample-app、イメージ名がappの場合、コンテナイメージのURLは次のようになります。

Terminal window
asia-northeast1-docker.pkg.dev/sample-project/sample-app/app:latest

サービスの名前はWebアプリケーションなので、かつDockerイメージ名と合わせてappとします。
リージョンは日本向けと仮定してasia-northeast1(東京リージョン)を選択します。
誰でもアクセスできるように認証のチェックボックスは外しておきます。

構成

コンテナの設定

コンテナ、ボリューム、ネットワーキング、セキュリティのタブを開きます。

コンテナポートは3000を指定します。
Ruby on Rails固有の設定ですが、DockerfileのCMDを見てみるとbin/thrustが実行されていることがわかります。
こちらはRuby on Rails用のHTTP2プロキシであるThrusterの起動コマンドなのですが、こちらはデフォルトはHTTPは80ポート、HTTPSは443ポートで待ち受けています。
Cloud Runでなるべく無料で使う最小インスタンス設定でthrusterを使うと、ダウンタイムが生じてしまうため、
プロキシの後ろで3000番ポートで待ち受けしているRailsのアプリケーションに直接アクセスするように設定します。
そのため、コンテナポートは3000を指定します。

ポート設定

変数とシークレット

次に、変数とシークレットのタブを開きます。
ここでは、先ほどSecret Managerに保存したRAILS_MASTER_KEYをCloud Runの環境変数として設定します。
環境変数として公開されるシークレットのセクションで、シークレットを追加ボタンをクリックします。
名前にはRAILS_MASTER_KEYを入力し、シークレットには先ほど作成したrails_master_keyを選択します。
バージョンはlatestを選択します。

選択し終わったら、完了ボタンをクリックします。

変数とシークレット

ボリュームのマウント

次に、ボリュームのタブを開きます。
ここでは、Cloud Storageのバケットをマウントして、SQLite3のデータベースファイルを永続化します。
ボリュームを追加ボタンをクリックします。

ボリュームのタイプはCloud Storageバケット,
ボリューム名は任意の名前でよいですが、今回はstorageとします。
バケットはあらかじめ作成したCloud Storageのバケットを選択します。

ボリュームの作成

入力したら、完了ボタンをクリックします。

マウントパスの設定

ボリュームを作成したら、コンテナタブに戻って、マウントパスを設定します。
ボリュームのマウントのセクションで、先ほど作成したボリュームを選択します。

名前は先ほど作成したstorageを選択します。
マウントパスは/rails/storageを指定します。
sample_appのDockerfileを確認するとWORKDIR/railsになっています。
つまり、Railsのアプリケーションは/railsディレクトリに配置されます。

Dockerfile
WORKDIR /rails

つぎにconfig/database.ymlを確認します。
productionの設定で、SQLite3のデータベースファイルはstorage/production.sqlite3のように
storageディレクトリに配置されます。
そのため、マウントパスは/rails/storageを指定します。

config/database.yml
production:
primary:
<<: *default
database: storage/production.sqlite3
cache:
<<: *default
database: storage/production_cache.sqlite3
migrations_paths: db/cache_migrate
queue:
<<: *default
database: storage/production_queue.sqlite3
migrations_paths: db/queue_migrate
cable:
<<: *default
database: storage/production_cable.sqlite3
migrations_paths: db/cable_migrate

他のWebアプリケーションの場合や、設定を変更した場合は、SQLite3のデータベースファイルが配置されるパスを指定してください。

ボリュームのマウント

Cloud RunからStorageへのアクセス権限の設定

Cloud RunからCloud Storageのバケットにアクセスするためには、Cloud Runのサービスアカウントに適切な権限を付与する必要があります。
画面上部の検索バーに「IAM」と入力して、IAMのページを開きます。

デフォルトのサービスアカウント(@development.gserviceaccount.com)の鉛筆アイコンをクリックして、編集画面を開きます。
次のようにロールを追加します。

  • run.developerと入力して、Cloud Run でデベロッパーを選択
  • iam.serviceAccountUserと入力して、サービスアカウントユーザーを選択
  • storage.adminと入力して、ストレージ管理者を選択

選択したら、画面最下部の保存ボタンをクリックします。

これでCloud RunのサービスアカウントにCloud Storageのバケットにアクセスする権限が付与されました。

https://cloud.google.com/run/docs/configuring/services/secrets?hl=ja#required_roles

リビジョンスケーリングの設定

次に、リビジョンスケーリングの設定をします。
SQLite3は単一のインスタンス向けなので、Cloud Runのインスタンスは1つに固定します。
最大インスタンス数を1に設定します。
最小インスタンス数は0に設定します。

起動時のブーストはチェックを入れておくとコールドスタート時の起動時間が短縮されますが、
今回はなるべく無料で運用したいので、チェックは外しておきます。
起動時のブーストを有効にすると、起動時間が短縮されますが、課金が発生する場合があります。

リビジョンスケーリング

Cloud Runの作成

設定が完了したら、画面最下部の作成ボタンをクリックします。

これでCloud Runのサービスが作成されます。
作成には数分かかりますので、しばらく待ちます。

作成中

Cloud RunのURLの確認

デプロイに成功すると、緑色のチェックマークが表示されます。
サービスのURLが表示されるので、クリックしてアプリケーションにアクセスします。

成功

トラブルシューティング

もしデプロイに失敗した場合は、ログのタブを開いて、エラーメッセージを確認してください。

ログの確認

予算アラートの設定

Cloud Runは無料枠があるため、ポートフォリオや小規模な個人開発のプロジェクトであれば、無料で運用可能ですが、
利用状況によっては課金が発生する可能性があります。
そのため、予算アラートを設定しておくことをおすすめします。
画面上部の検索バーに「予算」と入力して、予算のページを開きます。

予算の設定

予算を作成ボタンをクリックして、予算の作成画面を開きます。

予算の作成

範囲

任意の名前を入力、期間は月別、プロジェクトは今回作成したプロジェクトを選択します。
サービスはすべてのサービス、クレジットはチェックをつけます。
設定したら、画面最下部の次へボタンをクリックします。

予算の設定

金額

予算金額はここでは100円とします。
このように設定しておけば、月間100円を超えるとアラートが通知されます。
範囲を月別に設定しているので、月初にリセットされます。
設定したら、画面最下部の次へボタンをクリックします。

予算金額の設定

操作

次に、アラートの操作を設定します。
予算の金額を超えたときのセクションで、メール通知を受け取るにチェックを入れておくと、
予算を超えたときにメールで通知されます。
予算の割合の設定はデフォルトのままでも十分ですが、必要に応じて変更してください。
設定が完了したら、画面最下部の終了ボタンをクリックします。

予算の割合の設定

デプロイのスクリプトを追加

毎回イメージのビルド、プッシュ、Cloud Runのデプロイを手動で行うのは面倒なので、
スクリプトを作成して自動化します。
sample_appディレクトリにbin/deployという名前のファイルを作成します。

ハイライトされている箇所は適宜変更してください。
プロジェクトIDはGoogle Cloud Consoleのプロジェクトを選択すると調べることができます。

project id

bin/deploy
#!/bin/bash -e
docker build -t sample_app . --no-cache
PROJECT_ID="プロジェクトのIDを入力"
REPOSITORY="Artifact Registryのリポジトリ名を入力"
IMAGE_NAME="app"
REGION="asia-northeast1"
SERVICE_NAME="app"
IMAGE_TAG="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMAGE_NAME}:latest"
docker tag sample_app "$IMAGE_TAG"
docker run -it --volumes-from gcloud-config \
-v gcloud-config:/root/.docker \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
gcr.io/google.com/cloudsdktool/google-cloud-cli:stable \
bash -c "docker push $IMAGE_TAG"
docker run --rm --volumes-from gcloud-config \
gcr.io/google.com/cloudsdktool/google-cloud-cli:stable \
gcloud run deploy "$SERVICE_NAME" \
--image "${IMAGE_TAG}" \
--region "${REGION}" \
--project "${PROJECT_ID}"

実行権限を付与します。
パスワードの入力を求めらるので、パスワードを入力してください。

Terminal window
sudo chmod +x bin/deploy

継続的デプロイの設定

毎回デプロイスクリプトを実行するのも大変なので、継続的デプロイを設定します。
Cloud RunはCloud Buildと連携して、GitHubから自動的にデプロイすることができます。
手元のパソコンからGitHubにコードをプッシュすると、GitHubからCloud Buildがトリガーされ、
自動的にDockerイメージのビルド、Artifact Registryへのプッシュ、
Cloud Runへのデプロイが行われます。

継続的デプロイ

GitHubのリポジトリを作成しましょう。

リポジトリの作成

リポジトリを作成したら...or push an existing repository from the command lineのセクションに表示されているコマンドを実行して、リポジトリを初期化します。

※アカウント名、リポジトリ名は適宜変更してください。

Terminal window
git remote add origin https://github.com/ihatov08/cloudrun-sqlite.git
git branch -M main
git push -u origin main

次にGoogle Cloud ConsoleのCloud Runのページで継続的デプロイの設定ボタンをクリックします。

現時点ではGoogle CloudとGitHubの連携がされていない場合は、認証をクリックして、GitHubの認証を行います。
また接続されたリポジトリで、今回作成したリポジトリを接続しましょう。

Cloud Buildの設定

設定完了後は次のような画面が表示されます。

Cloud Buildの設定

設定が終わったら次へボタンをクリックします。

次にビルドの設定を行います。

ビルド構成は、今回はmainブランチにpushされたときにビルドを実行するように設定します。
ビルドタイプはDockerfileを選択、ソースの場所は/Dockerfileに設定します。

ビルドの設定

設定が完了したら保存ボタンをクリックします。

設定が完了するとリポジトリからのデプロイが実行されます。

リポジトリからのデプロイ

どのような処理が行われているかログリンクをクリックしてみましょう。

ログ画面を見てみると、ビルドの概要で3個のステップが実行されていることがわかります。

  1. Build
  2. Push
  3. Deploy

つまり、Docker イメージのビルド、Artifact Registryへのプッシュ、Cloud Runへのデプロイが自動的に行われています。

ログ

適当にコードを変更して、GitHubにpushして、Cloud Runのデプロイが自動的に行われることを確認してみてください。

これでGitHubにPushするだけでCloud Runにデプロイされるようになりました。

【番外編】さらに無料に近づける..

ここまででCloud RunでWebアプリケーションをほぼ無料(3円/月)で動かすことができます。
さらに無料に近づける方法があります。
ここまでの方法では、アクセスがほとんどなくてもArtifact Registryで(1日当たり0.1円とはいえ)料金が必須でかかってしまいます。
コンテナレジストリであるArtifact Registryを使用せずにDocker Hubなどの外部のコンテナレジストリを使用することで、さらに無料に近づけることができます。

さらに無料に近づける

しかし、この方法には制約があります。
Cloud RunでDocker Hubなどの外部レジストリを使用する場合は、
2パターンの方法があります。

非公開イメージの場合

非公開のDockerイメージを使用する場合は、Artifact Registryのリモートリポジトリを経由する必要があります。
そのため、Artifact Registryの課金は避けられません。

公開イメージの場合

公開イメージの場合は、Artifact Registryを経由する必要がないので、課金を回避できます。
しかし、イメージを公開する必要があるため、ソースコードやDockerイメージを公開しても問題ない場合に限ります。
ポートフォリオなどの場合は、GitHubもPublicリポジトリで公開することが多いので、
Dockerイメージも公開してしまって問題ないでしょう。
また後で詳しく解説しますが、外部レジストリかつ公開イメージの場合は、latestタグを使用するとキャッシュが効いてしまうのか、
デプロイしても更新されないことがあります。
そのため、毎回タグを変更してデプロイする必要があります。
対応策については後ほど説明します。

制約のある外部レジストリの使用

つまり外部のレジストリを使い無料で運用するには、以下の制約があります。

  • イメージを公開する必要がある
  • 継続的デプロイ(Cloud Build)が使えない

これらのデメリットを受け入れられる場合は、外部のコンテナレジストリを使用することで、さらに無料に近づけることができます。

では、外部のコンテナレジストリを使用する方法を説明します。

継続的デプロイを停止する

外部レジストリかつ無料で運用するためには、継続的デプロイを停止する必要があります。
Cloud Runのページで、継続的デプロイの設定を開きます。
無効にするボタンをクリックして、継続的デプロイを無効にします。

継続的デプロイの設定

Docker Hubのアカウントを作成

Docker Hubのアカウントを作成します。

https://hub.docker.com/

ターミナルからログイン

アカウントを作成したら、ターミナルからDocker Hubにログインします。
次のコマンドを実行して、Docker Hubにログインします。

Terminal window
docker login

ブラウザが開くのでConfirmボタンをクリックします。

イメージのpush

次に、Docker Hubにイメージをプッシュします。
今回はsample_appという名前でイメージをプッシュします。
<Docker Hubのユーザー名>の部分には、Docker Hubのユーザー名を入力してください。

Terminal window
docker tag sample_app <Docker Hubのユーザー名>/sample_app:latest

タグをつけ終わったらイメージをプッシュします。
<Docker Hubのユーザー名>の部分には、Docker Hubのユーザー名を入力してください。

Terminal window
docker push <Docker Hubのユーザー名>/sample_app:latest

イメージをpushしたら、Docker Hubにアクセスして、イメージがアップロードされていることを確認します。

https://hub.docker.com/repositories

イメージの確認

Cloud Runの設定

次に、Cloud Runの設定を行います。

Cloud Runのサービスの詳細ページで新しいリビジョンの編集とデプロイボタンをクリックします。

新しいリビジョンの編集とデプロイ

コンテナイメージのURLを修正します。

<Docker Hubのユーザー名>/sample_app:latestのように、Docker Hubのユーザー名とイメージ名を指定します。
たとえばDocker Hubのユーザー名がihatov08の場合、次のようになります。

Terminal window
ihatov08/sample_app:latest

コンテナイメージのURL

修正したら、画面下部のデプロイボタンをクリックします。

Cloud Runのリビジョンがデプロイされるので、成功することを確認します。

Cloud Runのリビジョン

デプロイのURLを修正

前述したとおり、外部のコンテナレジストリを使用する場合は、
毎回タグを変更してデプロイする必要があります。
そのため、デプロイのURLも変更する必要があります。
イメージのタグにタイムスタンプを付けて、毎回異なるタグを使用するようにします。

bin/deployのスクリプトを修正します。
DOCKER_HUB_USERNAMEの部分には、Docker Hubのユーザー名を入力してください。
GCP_PROJECT_IDの部分には、Google CloudのプロジェクトIDを入力してください。
イメージのタグにタイムスタンプを付けるために、TIMESTAMP変数を追加します。

bin/deploy
#!/bin/bash -e
TIMESTAMP=$(date +%Y%m%d%H%M%S)
DOCKER_HUB_USERNAME="Docker Hubのユーザー名を入力"
IMAGE_NAME="sample_app"
GCP_PROJECT_ID="プロジェクトのIDを入力"
docker build -t ${DOCKER_HUB_USERNAME}/${IMAGE_NAME}:$TIMESTAMP . --no-cache
docker push ${DOCKER_HUB_USERNAME}/${IMAGE_NAME}:$TIMESTAMP
docker run --rm --volumes-from gcloud-config \
gcr.io/google.com/cloudsdktool/google-cloud-cli:stable gcloud run deploy app \
--image ${DOCKER_HUB_USERNAME}/${IMAGE_NAME}:$TIMESTAMP \
--region asia-northeast1 \
--project ${GCP_PROJECT_ID}

スクリプトの修正によって、毎回異なるタグでデプロイされるようになります。
これで制約はあるものの、外部のコンテナレジストリを使用して、Cloud RunでWebアプリケーションを無料で動かすことができます。

まとめ

Cloud Runを使ってWebアプリケーションを無料で動かす方法を学びました。
他のPaaSと比較しても料金が安く、かつAWSと比較すると使いやすいのが特徴です。
ぜひ皆さんもポートフォリオや小規模な個人開発のプロジェクトで活用してみてください。