👶

[Google Cloud] [Go] 初めてのCloud Runとデプロイまで

2024/07/22に公開

始めに

普段はモバイルエンジニアとして働いていますが、個人アプリでGoでAPIを作成して、Google Cloudのサービスの一つであるCloud Runを使ってデプロイしたので、まとめます。
全く畑違いだったので色々困ったことがあってそれも書いておきたいと思います。

そもそもCloud Runとは

スケーラブルなインフラストラクチャ上でコンテナを直接実行できるマネージドコンピューティングプラットフォームです。
https://cloud.google.com/run?hl=ja

コンテナイメージをビルドできるものであれば、Github上のレポジトリを指定して直接デプロイすることも可能です。
またGoogle CloudのArtifact Registryリポジトリにコンテナをpushしてデプロイすることもできます。

ここら辺が参考になります。
https://cloud.google.com/run/docs/quickstarts?hl=ja

サービスの作成

プロジェクトごとにサービスを作成する必要があります。
「サービスの作成」を押して作成していきます。

ここら辺は難しいことはあまりなくドキュメントを見ながら進められるかと思います。

https://cloud.google.com/run/docs/developing?hl=ja

SQLサーバーとの接続

自分の場合はSQLを使いたかったので、Google CloudのSQLサーバーと接続することにしました。
https://cloud.google.com/sql-server?hl=ja

「インスタンスの作成」を押してインスタンスを作成していきます。

インスタンスを作成して「データベース」からDBを作成します。

完了したらCloud Runに戻り、先ほど作成したサービスの詳細に遷移します。
「新しいリビジョンの編集とデプロイ」を押して編集画面に移動します。

Cloud SQL接続から先ほど作成したインスタンスを選択します。

「変数とシークレット」からSQLサーバーで作成したDB情報を埋め込みます。

ドキュメントはここら辺です
https://cloud.google.com/sql/docs/postgres/connect-run?hl=ja

コード上

コードからSQLに接続するための処理を書いていきます。
実際に接続するためにはCloud SQL Connectorを使用します。
https://github.com/GoogleCloudPlatform/cloud-sql-go-connector

https://cloud.google.com/sql/docs/mysql/connect-connectors?hl=ja

func connectWithConnector() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("%s environment variable not set.", k)
		}
		return v
	}

	var (
		dbUser                 = mustGetenv("DB_USER")
		dbPass                 = mustGetenv("DB_PASS")
		dbName                 = mustGetenv("DB_NAME")
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME")
	)

	dsn := fmt.Sprintf("user=%s password=%s database=%s", dbUser, dbPass, dbName)
	config, err := pgx.ParseConfig(dsn)
	if err != nil {
		return nil, err
	}

	d, err := cloudsqlconn.NewDialer(context.Background())
	if err != nil {
		return nil, err
	}

	config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
		return d.Dial(ctx, instanceConnectionName)
	}
	dbURI := stdlib.RegisterConnConfig(config)
	dbPool, err := sql.Open("pgx", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

自分の場合はgormを使っているので、上記で作成したものを渡してあげます。

以上でCloud Runからデプロイするとデプロイが成功するようになると思います。

困ったこと

デプロイエラー

Cloud Runでデプロイがコケると

Revision 'service-name' 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

デプロイに失敗した場合、多分ほとんど全て上記のエラーメッセージが表示されます。
ですが、この内容だけだと何が悪いのかわからないのでログエクスプローラーで調査する必要があります。
ログエクスプローラー上でも表示される情報は少ないので探偵のように思案しながら進めました🙃

Firebase Authenticationとの接続

自分の場合は認証をFirebase Authenticationに寄せました。
Google Cloudのサービス同士なのであまり意識せずに良い感じにGoのコードからAdmin SDKを使って認証を行うことができます。

ただし、サービスアカウントがFirebase上のプロジェクトと一致していないと失敗するので注意してください。

Firebaseのコンソールの設定のプロジェクトIDと

Google Cloudのプロジェクト選択画面に表示されるIDが一致していること

先にFirebaseのプロジェクトを作成しているとGoogle Cloud上にもプロジェクトが表示されていると思います。
(考えてみれば当たり前ですが、自分はそこに気が付かなくて時間を溶かしました👶)

まとめ

Firebase Authenticationを使いたくてCloud Runを使いましたが全く知らない状態でも使いやすいなと思いました。
バックエンドを開発してみたい!の気持ちで本当に0からやってみた自分でもデプロイでき、APIを使うことができるようになって感無量です。

Discussion