Cloud Run
にGo
で作成したAPI
をデプロイしようと思ったところ、うまくいかなかった。
調査してみたところ、データーベースに接続できずに落ちているっぽいとのこと。
ちょっとなんでかわからないけど(今思い返せば、Docker
起動していた? という不安がある)、ローカルのDB
に接続できないので、いずれ接続する予定だったので、Cloud SQL
に接続し、それでCloud Run
にデプロイしてみようという風に思い立った。
Cloud SQLに登録する
Cloud Run から Cloud SQL for MySQL に接続するがある。
公式があるので、こちらを参考にする。
なお、今回サーバーはローカル(net/http
)で起動することにする。
インスタンスを作成する
- Google Cloud コンソールで Cloud SQL の [インスタンス] (https://console.cloud.google.com/sql?hl=ja&_ga=2.145632700.968950133.1716041931-758618644.1700836939)ページに移動する。
- インスタンスを作成 をクリック。
- [MySQL を選択] をクリック。
インスタンスを作成するには、まず Compute Engine API を有効にする必要があります。
という警告が出るので、API
を有効にする。
インスタンスID、パスワード、を登録。
My SQL
のバージョンを8にし、Cloud SQL
のエディションはEnterprise
にする。
プリセットをいったん開発環境にして、リレージョンを東京、ゾーンをシングルに設定する。
構成オプションを開き、とりあえず一番小さい1 vCPU
、3.75 GB
を選択してみる。
で、インスタンスを作成する。
構成オプションはとりあえず、最小で不満があればあげていく方法で問題ないらしい。
DBの作成
インスタンスのデータベースにいき、データーベースの作成をクリックする。
今回インスタンスの作成をし、データーベースの作成をしていなかったので、エラーが出続け、悩まされた。
接続を試みる
まず接続をしてみたところ、
$ go run main.go
2024/05/26 00:41:05 cloudsqlconn.NewDialer: failed to create default credentials: google: could not find default credentials. See https://cloud.google.com/docs/authentication/external/set-up-adc for more information
exit status 1
というエラーが出た。
どうやら認証情報が見つかりませんとのこと。
対象のディレクトリでgcloud auth application-default login
を実行し、ログインを完了させた。
ソースコードは公式を参考に下記のように。
package db
import (
"context"
"database/sql"
"fmt"
"log"
"net"
"os"
"cloud.google.com/go/cloudsqlconn"
"github.com/go-sql-driver/mysql"
gmysql "gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
type Model struct {
gorm.Model
}
func mustGetenv(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_connector.go: %s environment variable not set.", k)
}
return v
}
func InitDB() {
var (
dbUser = mustGetenv("DB_USER") // e.g. 'my-db-user'
dbPwd = mustGetenv("DB_PASS") // e.g. 'my-db-password'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
usePrivate = os.Getenv("PRIVATE_IP")
)
d, err := cloudsqlconn.NewDialer(context.Background())
if err != nil {
fmt.Errorf("cloudsqlconn.NewDialer: %w", err)
return
}
var opts []cloudsqlconn.DialOption
if usePrivate != "" {
opts = append(opts, cloudsqlconn.WithPrivateIP())
}
mysql.RegisterDialContext("cloudsqlconn",
func(ctx context.Context, addr string) (net.Conn, error) {
return d.Dial(ctx, instanceConnectionName, opts...)
})
dbURI := fmt.Sprintf("%s:%s@cloudsqlconn(localhost:3306)/%s?parseTime=true",
dbUser, dbPwd, dbName)
sqlDB, err := sql.Open("mysql", dbURI)
if err != nil {
log.Fatalf("sql.Open: %v", err)
}
// Open a connection to the database using the gorm package
DB, err = gorm.Open(gmysql.New(gmysql.Config{
Conn: sqlDB,
}), &gorm.Config{})
if err != nil {
log.Fatalf("gorm.Open: %v", err)
}
fmt.Println("データベースに接続しました")
}
これで実行したところ、
データベースに接続しました
2024/05/28 00:26:14 defaulting to port 8080
2024/05/28 00:26:14 listening on port 8080
無事に接続できた。
課金具合が予想を超えている
Cloud SQL
の課金体系がいまいち理解できていない。
ただコンソールを見る限り、想像を超える課金が行われている。
使用していない時はインスタンスを停止してその場を凌ぐけど、しっかりと理解をしたい。