# GormでCloud SQLに接続する

5 min read
Table of Contents

Cloud RunGoで作成したAPIをデプロイしようと思ったところ、うまくいかなかった。

調査してみたところ、データーベースに接続できずに落ちているっぽいとのこと。

ちょっとなんでかわからないけど(今思い返せば、Docker起動していた? という不安がある)、ローカルのDBに接続できないので、いずれ接続する予定だったので、Cloud SQLに接続し、それでCloud Runにデプロイしてみようという風に思い立った。

Cloud SQLに登録する

Cloud Run から Cloud SQL for MySQL に接続するがある。

公式があるので、こちらを参考にする。

なお、今回サーバーはローカル(net/http)で起動することにする。

インスタンスを作成する

  1. Google Cloud コンソールで Cloud SQL の [インスタンス] (https://console.cloud.google.com/sql?hl=ja&_ga=2.145632700.968950133.1716041931-758618644.1700836939)ページに移動する。
  2. インスタンスを作成 をクリック。
  3. [MySQL を選択] をクリック。

インスタンスを作成するには、まず Compute Engine API を有効にする必要があります。

という警告が出るので、APIを有効にする。

インスタンスID、パスワード、を登録。

My SQLのバージョンを8にし、Cloud SQL のエディションはEnterpriseにする。

プリセットをいったん開発環境にして、リレージョンを東京、ゾーンをシングルに設定する。

構成オプションを開き、とりあえず一番小さい1 vCPU3.75 GBを選択してみる。

で、インスタンスを作成する。

構成オプションはとりあえず、最小で不満があればあげていく方法で問題ないらしい。

DBの作成

インスタンスのデータベースにいき、データーベースの作成をクリックする。

今回インスタンスの作成をし、データーベースの作成をしていなかったので、エラーが出続け、悩まされた。

接続を試みる

まず接続をしてみたところ、

Terminal window
$ 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("データベースに接続しました")
}

これで実行したところ、

Terminal window
データベースに接続しました
2024/05/28 00:26:14 defaulting to port 8080
2024/05/28 00:26:14 listening on port 8080

無事に接続できた。

課金具合が予想を超えている

Cloud SQLの課金体系がいまいち理解できていない。

ただコンソールを見る限り、想像を超える課金が行われている。

使用していない時はインスタンスを停止してその場を凌ぐけど、しっかりと理解をしたい。

My avatar

Thanks for reading my blog post! Feel free to check out my other posts or contact me via the social links in the footer.


More Posts

Comments