最初に
本記事の内容は、サーバーサイドにほとんど触れてこなかったUnityエンジニアに向けて、最近の主流構成を学びながら少しずつサーバーの知識を身につけられるハンズオン形式で進めます。この記事が、サーバーサイドに対する理解を深める一助になれば幸いです。
本記事の対象者は以下の通りです。
- A Tour of Goを一通り終わらせたが次に何をするべきかわからない初心者サーバーエンジニア
- gRPCについて学びたいが、Unityとの関連性も知りたい初学者
- なんとなくGoやgRPCについては理解できるけど、具体的な仕組みについて知りたいUnityエンジニアの方
また、今回のハンズオン記事は全7章が存在します。
こちらから他の章も見ていただけると嬉しいです!
「第一章、環境構築」
「第二章、Cloud Runへのデプロイ」
「第三章、CI/CDパイプライン構築」
「第四章、Firebaseプロジェクトの作成とFirebaseSDK導入」
「第五章、FirebaseSDKを用いたアカウント作成とログイン実装」
今回の環境
- OS : MacOS
- IDE : GoLand
- Gitクライアント : Fork
前提
以下の記事を終えているか、チャットアプリケーションを作るにあたって、必要な設定をGCP上で行う準備ができていることを前提としています。
サーバーサイドなんもわからんアナタに向けたハンズオン Unity × gRPC × Go × Firebase × Docker 〜第一章、環境構築〜
また、記事の内容を自由に学習できるよう、GitHub上に公開リポジトリを作成しました。各ステップに対応したバージョンをReleasesとして登録しているので、興味のあるステップから学習を始められます。
上記リポジトリ内容を使用して特定のステップから始める場合はリポジトリをForkするか、手元にDownloadなどをしてから進めるようお願いします。
1. Google Cloudにアクセスしてプロジェクトを作成する
最初に、Google Cloudプロジェクトの作成を行います。
ここでは、Google Cloud Platform (GCP)にアクセスし、プロジェクトを新規作成します。Google Cloudのコンソールページにアクセスし、Googleアカウントでログインしてください。
ログインするとダッシュボードが表示され、利用可能なプロジェクトや各種リソースが確認できます。今回は既に無料トライアルを適用した状態にしています。読者の方も、無料トライアルができる状態であれば、試してみることをお勧めします。
ダッシュボードのトップバーにある「プロジェクトの選択」ボタンをクリックします。
プロジェクト一覧ダイアログが表示されるので、「新しいプロジェクト」をクリックします。
「プロジェクト名」に任意の名前を入力します。
今回はgrpc-chat-app
という名前のプロジェクトを作成します。プロジェクトIDは一度設定すると変更できないので、注意が必要です。
名前を設定後、「作成」をクリックすると、新しいプロジェクトが作成され、プロジェクトがGCP上で利用可能な状態になります。
コンソールページに戻ったあと、プロジェクト名を確認すると、先ほど作成したプロジェクトの名前になっていることが確認できます。
2. Google Cloudプロジェクトのセットアップ
Google Cloudプロジェクトの作成が終わったら、次はセットアップを行なっていきます。
APIとサービスの有効化
このハンズオンで使用する「Cloud Run」や「Cloud Build」などのサービスを利用するためには、対応するAPIを有効化する必要があります。
画面上部にある検索窓から、「API」で検索をかけ、「APIとサービス」を見つけたらクリックしてください。
次に、「APIとサービスを有効にする」をクリックしてください。
まずは「Cloud Run API」を有効化しましょう。
Cloud Runは、コンテナ化されたアプリケーションをサーバーレスで実行できるプラットフォームです。
gRPCサーバーをCloud Run上でデプロイするために、Cloud Run Admin API を有効化する必要があります。APIを有効化することで、Google CloudからCloud Runへのアクセスが許可され、Cloud Runのサービスがプロジェクト内で利用できるようになります。
サーバーレスって?
サーバーレスという言葉を聞くと、「サーバーがない」という意味に感じるかもしれませんが、実際にはサーバーは使用されています。サーバーレスとは、「サーバーの管理をユーザーが行わない」 という意味です。
通常、アプリケーションを動かすにはサーバーを準備し、設定し、運用する必要がありますが、サーバーレスの場合、その部分をすべてクラウドサービス側(Google Cloudなど)が自動でやってくれるのです。
特にCloud Run は、ユーザーからのアプリケーションに対してのアクセス・リクエストの量に応じて自動でコンテナの数を増やしたり減らしたりしてくれます。アクセスが増えるとコンテナを増やして処理し、アクセスが少ないときやアクセスがないときには、コンテナの数を減らしてリソースを節約します。これにより、無駄なリソースを使わないため、コストが抑えられます。
検索窓に「Cloud Run」と入れ、Cloud Run Admin APIを有効化してください。
続いて「Cloud Build API」を有効化していきましょう。
Cloud Build は、ソースコードからDockerイメージをビルドし、コンテナレジストリにプッシュするCI/CDツールです。
Cloud Buildを使うことで、GitHubリポジトリにコードをプッシュした際に、自動でDockerイメージをビルドし、Cloud Runへデプロイするパイプラインを構築できます。
コンテナレジストリって?
Docker イメージや他のコンテナイメージを保存、管理、配信するための場所やサービスのことです。例えば、開発者がアプリの実行環境をパッケージ化したコンテナをこのレジストリに保存しておくことで、クラウドや他のサーバーに簡単に取り出してデプロイできます。これにより、アプリを複数の環境で一貫して動作させることが可能になります。
それでは検索窓に「Cloud Build API」と打ち込んで、「Cloud Build API」を有効化してください。
最後に「Secret Manager API」を有効化します。こちらは機密データ(APIキー、パスワード、証明書など)を安全に保存し、アクセスを管理するためのGoogle Cloudのサービスです。
このAPIを使用することで、機密情報をアプリケーションコードに埋め込む必要がなくなり、より安全にデータを管理できます。
後ほどCI/CDパイプライン構築でリポジトリとGCPを接続するために使用します。
Artifact Registryでリポジトリの作成
Google Cloud上でコンテナイメージを管理するためには、Artifact Registryにリポジトリを作成する必要があります。
Artifact Registryとは、Google Cloud上でコンテナイメージやソフトウェアのパッケージを保存・管理するために使用できるサービスです。
たとえば、アプリケーションのDockerビルド後に作成されるDockerイメージをここに保存し、クラウド上でアプリケーションをデプロイする際に使用できます。Artifact Registryは、イメージの保存だけでなく、セキュリティスキャンやアクセス制御も提供しています。
それではさっそく、作成してみましょう。
Google Cloudコンソール画面上の検索窓に「Artifact Registry」と入れ、検索結果をクリックして、Artifact Registry管理画面へ移動してください。
続いて、「リポジトリを作成」をクリックして、リポジトリの詳細を設定します。
ここでいう「リポジトリ」って?
アプリケーションのビルド成果物(アーティファクト)を格納するための「保管場所」です。リポジトリは、Dockerイメージやnpmパッケージなどのアーティファクトを一元管理し、必要なときに引き出せるようにするためのスペースを提供します。
詳細設定は以下の通り行います。
-
名前:
リポジトリの名前を入力します。今回はプロジェクト名に沿った形でgrpc-chat-server
としました。 -
形式:
「Docker」を選択します。これにより、Dockerイメージを保存できるリポジトリが作成されます。 -
モード:
「標準」を選択します。 -
ロケーションタイプ:
「リージョン」または「マルチリージョン」を選択します。今回は「リージョン」を選択し、us-central1
(アイオワ)を設定します。- 「リージョン」は、データが一つの物理的な場所に保管されるため、アクセス速度が速く、料金が低いことが特徴です。
- 「マルチリージョン」は、データの冗長性が高く、異なる場所にバックアップがあるため、可用性が高いことが特徴です。
設定が完了したら、「作成」ボタンを押してリポジトリを作成します。
これでArtifact Registryにコンテナイメージを保存するためのリポジトリが準備できました。
アクセス権限の設定
Google Cloud プロジェクトを管理・運用するにあたって、Google Cloud StorageやCloud Runなどのリソース管理をするために、適切な権限を設定する必要があります。
理由としては以下が挙げられます。
-
アクセス制御とセキュリティ:
権限を付与することで、プロジェクト内のリソースに誰がアクセスできるか、どの操作が可能かを細かく制御できます。これにより、悪意のあるアクセスや、誤操作によるデータ漏洩・破損を防ぐことができます。セキュリティのベストプラクティスとしても、「最小権限の原則」にすることが推奨されています。たとえば、デプロイや設定変更が許可されたアカウント以外で行われないように制限することが可能です。 -
責任分担と役割の明確化:
権限を適切に設定することで、ユーザーやサービスごとの役割分担が明確になります。特定の権限を持ったユーザーやサービスが、どのリソースを操作できるかを決めることで、責任範囲を限定できます。
それでは権限の設定をしていきましょう。
Google Cloudコンソール画面上の検索窓でIAMと入力し、「IAMと管理」をクリックしてください。
左のメニューから「サービスアカウント」をクリックしてください。
ここで、サービスアカウントを新規に作成します。
サービスアカウントとは、アプリケーションやサービスなどの、人以外に対して権限を付与するために使用する特別なアカウントです。たとえば、Cloud Runにデプロイされたアプリケーションがこのアカウントを使用して、Cloud Storageにアクセスし、データの読み書きを行います。
それではサービスアカウントを作成していきましょう。画面上の方にある「サービスアカウントを作成」をクリックしてください。
詳細を入力していきましょう。
-
サービス アカウント名:
プロジェクト名に基づいた分かりやすい名前を指定します。今回はプロジェクト名をそのまま流用し、「grpc-chat-app」という名前にします。 - サービス アカウント ID:自動的に生成されるためそのままで構いません。
- サービス アカウントの説明:このサービス アカウントの役割や目的を説明するテキストを入力します。
入力したら「作成して続行」をクリックします。
次に、サービスアカウントがプロジェクト内のリソースに適切なアクセス権を持つように、必要なロールを割り当てます。以下の3つの権限を設定してください。
- Cloud Run 閲覧者:Cloud Run リソースのステータスを確認する権限
- Cloud Build サービス アカウントユーザー:Cloud Buildのジョブを実行する権限
- Storage オブジェクト管理者:Cloud Storage バケット内のファイルを操作するための権限
すべての設定が完了したら、「続行」をクリックして設定を完了します。
これにより、作成したサービスアカウントがプロジェクトに追加され、必要なリソースへのアクセスができるようになります。
サービスアカウントキーの作成
Google Cloud プロジェクト側での設定は一通り完了しました。
次に、サービスアカウントの鍵を作成してCLIからGoogle Cloudの操作を行えるように設定していきましょう。
サービスアカウントキーは、アプリケーションやサービスがGoogle Cloudのリソースにアクセスするための認証情報です。
例えば、Cloud Runにデプロイしたアプリが、Cloud Storageにデータを保存したり読み込んだりする際に、この鍵を使ってアクセスを認証します。
Google Cloudコンソールから「IAM と管理」画面へ移動し、「サービス アカウント」を開いて、先ほど作成したサービスアカウントをクリックしてください。
「キー」と書かれたタブへ移動し、「鍵を追加」から「新しい鍵を作成」をクリックします。
「作成」を押すと、鍵がダウンロードされるので、このファイルを安全な場所に保管してください。この鍵を紛失したり、他人に知られるとセキュリティリスクが高くなるのでご注意ください。
Google Cloud SDK のインストール
ターミナルを開いて、Google Cloud SDKをインストールしていきましょう。
Google Cloud SDKをインストールすることで、ローカル環境からGoogle Cloudのリソースを管理できるCLIツールが使えるようになります。
サイトからDL、及びインストールする場合は以下のリンクから可能です。
Cloud SDK - ライブラリとコマンドライン ツール | Google Cloud
今回は、brew
コマンドを使用して、インストールを行います。ちなみに、--cask
は、brew
(Homebrew)コマンドにおいて、MacOSアプリケーションをインストールするためのオプションです。
brew install --cask google-cloud-sdk
gcloud コマンドによる初期設定
Google Cloud SDKインストール後、gcloud init
コマンドを使用してGoogle Cloud CLIの初期設定を行います。
gcloud init
上記を実行すると、Googleアカウントへのログインが求められます。
You must sign in to continue. Would you like to sign in (Y/n)?
yキーを入力して、アカウントログインに進んでください。
ログイン後にどのプロジェクトを使用するか、リスト形式で尋ねられるので、該当のプロジェクトに割り当てられている数字を入力してください。
Pick cloud project to use:
[1] beaming-talent-436001-n3
[2] grpc-chat-app
[3] Enter a project ID
[4] Create a new project
Please enter numeric choice or text value (must exactly match list item):
今回、私の場合だと2を入力します。
初期設定が完了すると、今後のコマンドは選択したプロジェクトに適用されます。
.
.
.
Some things to try next:
* Run `gcloud --help` to see the Cloud Platform services you can interact with. And run `gcloud help COMMAND` to get help on any gcloud command.
* Run `gcloud topic --help` to learn about advanced features of the CLI like arg files and output formatting
* Run `gcloud cheat-sheet` to see a roster of go-to `gcloud` commands.
3. Docker イメージを Artifact Registry にプッシュする
次に、Docker イメージをArtifact Registryにプッシュするための手順を説明します。Artifact Registryは、先ほども説明した通り、Docker コンテナイメージを保存し、管理するためのサービスです。
Artifact Registry への認証設定
最初に、以下のコマンドを実行して、Docker がArtifact Registryにアクセスできるように認証情報を設定します。
gcloud auth configure-docker us-central1-docker.pkg.dev
このコマンドは、Docker の設定ファイル(通常は ~/.docker/config.json
)に認証情報を追加しするためのものです。これにより、Docker クライアントが指定されたArtifact Registry内のレジストリ(us-central1-docker.pkg.dev
)にアクセスするときに、Google Cloud の認証情報を使用するようになります。
実行後、表示される確認メッセージに Y
を入力し、続行します。
Adding credentials for: us-central1-docker.pkg.dev
.
.
.
Do you want to continue (Y/n)?
これで、Artifact RegistryにDockerイメージをプッシュするための認証情報が設定されます。
Docker configuration file updated.
Dockerイメージのビルド
Cloud Runで動作するコンテナは、特定のアーキテクチャ(例: x86_64
)に対応している必要があります。Apple Silicon (M1, M2 Mac) のような ARM アーキテクチャでビルドされたイメージには対応していません。
そのため、以下のように x86_64
アーキテクチャでイメージをビルドします。
docker buildx build --platform linux/amd64 -t us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server:v1.0 .
コマンドの意味は以下の通りです。
-
docker buildx build
:
Docker Buildxというビルド機能を使用してビルドを行うコマンドです。 -
-platform linux/amd64
:
このオプションは、ターゲットのプラットフォームを指定します。linux/amd64
は x86_64 アーキテクチャ用の Linux 環境を指します。Apple Silicon (M1/M2) のような ARM アーキテクチャの Mac を使用している場合でも、x86_64 向けのイメージをビルドするために使用します。 -
-t us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server
:
t
はタグを付けるためのオプションです。このオプションの後に指定された文字列がイメージ名およびリポジトリです。us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server
は、Google Cloud Artifact Registryの特定のリポジトリを指しており、ビルドされたイメージがこのリポジトリに保存されるようになります。- イメージ名のあとに
:v1.0
と付け足しています。これがタグとなります。タグを付けることで、同じ名前のDockerイメージでも異なるバージョンを識別できるようになります。たとえば、latest
やv1.0
のようなタグを使うことで、特定のバージョンのイメージを容易に区別し、管理できます。タグは必須ではないのですが、できれば付けておくことを推奨します。Dockerイメージをビルドする際にタグを付けない場合、デフォルトでlatest
タグが適用されます。
- イメージ名のあとに
-
.
(ドット):
現在のディレクトリをビルドコンテキストとして指定しています。このディレクトリ内にあるDockerfile
や必要なファイルを使用してビルドが行われます。
結果が以下のようになれば、ビルド完了です。
[+] Building 30.2s (13/13) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile
.
.
.
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/{文字列}
What's next:
View a summary of image vulnerabilities and recommendations → docker scout quickview
Artifact Registryへのプッシュ
ビルドが完了したら、以下のコマンドで Docker イメージを Artifact Registry にプッシュします。
docker push us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server
このコマンドで、grpc-chat-server
という名前のイメージを、grpc-chat-app
プロジェクトのArtifact Registryにプッシュします。
Using default tag: latest
The push refers to repository [us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server]
.
.
.
latest: digest: sha256:{ランダムな文字列が表示されると思います} size: 3249
実行後、イメージが grpc-chat-app
プロジェクトの grpc-chat-server
リポジトリにアップロードされ、Artifact Registry上で管理できるようになります。
4. Cloud Runへのデプロイ
タグv0.5に対応しています。
それではCloud Runへのデプロイを試してみましょう。
以下のgcloud
コマンドを使用してみてください。
gcloud run deploy grpc-chat-server \
--image us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--use-http2
コマンドの意味は以下の通りです。
-
--image
:
Artifact Registryにプッシュ済みのDockerイメージを指定します。 -
-platform managed
:
Googleのマネージドプラットフォームを使用することを指定しています。これにより、インフラ管理の負担を軽減できます。 -
--region us-central1
:
デプロイするリージョンです。適宜変更できます。ユーザーがアクセスしやすいリージョンを選んでください。 -
--allow-unauthenticated
:
認証なしで誰でもサービスへアクセスできるようにするオプションです。後から変更することも可能です。 -
--use-http2
:
追加することで、Cloud RunがHTTP/2通信を有効にします。Cloud RunではデフォルトでHTTP通信を期待するのですが、このオプションをつけることで、HTTP/2通信を使えるようになります。
実は今回のコマンド実行では失敗してしまいます。
X Deploying new service...
- Creating Revision...
. Routing traffic...
✓ Setting IAM Policy...
Deployment failed
ERROR: (gcloud.run.deploy) Revision 'grpc-chat-server-00001-bhg' is not ready and cannot serve traffic.
The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable.
Logs for this revision might contain more information.
Logs URL: {URL}
For more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start
エラーメッセージによると、Cloud Runにデプロイされたコンテナが、指定されたポート(PORT=8080
)でリッスンしていないことが原因のようです。
実はCloud Runでは、デフォルトで環境変数 PORT=8080
が設定されており、コンテナはこのポートでリクエストを受け取るように設定する必要があります。しかし、今回だと 50051
番ポートでリッスンしているため、このエラーが発生しています。
50051
番ポートを使用していたのは、gRPCの標準的なポートとして一般的に使われるためです。gRPCのサーバーは通常、50051
番ポートでリッスンすることが多く、gRPCの公式ドキュメントやチュートリアルでもこのポートがよく使用されています。
まとめると以下の通りとなります。
- 50051:gRPCサーバーの標準ポート
- 8080:Cloud Runが期待するポート(デフォルト設定)
もちろんCloud run側のサービス設定で変更をすることもできるのですが、今回はコンテナ側でポートを8080
に合わせる形に変更していきましょう。
main.go
を開いてください。
現状は以下のようになっていると思います。
const (
port = ":50051"
)
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "grpc-chat-app-sample/gen/api/helloworld"
)
Cloud Runでは PORT
環境変数からポートを取得します。
なので、以下のように 8080
番ポートになるように修正してください。
const (
port = ":8080" // ここを変更
)
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "grpc-chat-app-sample/gen/api/helloworld"
)
合わせてプロジェクト下にあるDockerfileのEXPOSE
の番号も変更する必要があります。
このEXPOSE
コマンドは、Dockerコンテナが外部と通信するために使うポート番号を指定するものです。この設定によって、コンテナ内でアプリケーションがどのポートで待ち受けるかを宣言するためのものです。
現在は以下の状態かと思います。
EXPOSE 50051
番号を8080
に直しましょう。
EXPOSE 8080
ここまで修正ができたら、gitにて変更をpush
してください。
では、再度Dockerイメージのビルドを行ってください。
docker buildx build --platform linux/amd64 -t us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server .
ビルドが完了したらpushしてください。
docker push us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server
もう一度、デプロイを試してみましょう。
gcloud run deploy grpc-chat-server \
--image us-central1-docker.pkg.dev/grpc-chat-app/grpc-chat-server/grpc-chat-server \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--use-http2
今度は無事成功しました!
Deploying container to Cloud Run service [grpc-chat-server] in project [grpc-chat-app] region [us-central1]
✓ Deploying... Done.
✓ Creating Revision...
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [grpc-chat-server] revision [grpc-chat-server-00011-r87] has been deployed and is serving 100 percent of traffic.
Service URL: https://grpc-chat-server-39141254863.us-central1.run.app
まとめ
今回の第二章では、Cloud Runの利用によって、サーバーレス環境でのデプロイを体験しました。
今回のハンズオンでは以下のことを学びました。
- Google Cloudプロジェクトの作成とセットアップ
- サービスアカウントと権限の設定
- gRPCサーバーのコンテナ化とデプロイ
- ポートの適切な設定と修正
まだまだわからない単語もあると思いますので、この段階で不明点は改めて調べてみることをお勧めします。
次回はCI/CDパイプライン構築に挑戦していきます。
もしも記事の中で進められない箇所があったら、Xなどでご連絡ください。