💡

Cloud Functions + Cloud SQL をローカルで立ち上げようとしてSocket Pathでハマった

2022/11/08に公開

概要

  • Cloud Functions内でCloud SQLにアクセスしたかった
  • Cloud Functionsをローカルでテストしたかった(DB自体はリモート)

実装

Cloud FunctionsのローカルテストにはFunctions Frameworkを使います。
https://cloud.google.com/functions/docs/functions-framework?hl=ja

また、Cloud SQLにローカルから接続するにはCloud SQL Auth Proxyを使います。
https://cloud.google.com/sql/docs/postgres/sql-proxy?hl=ja#macos-64-bit

実装

.
├── functions/
│   ├── build/
│   ├── cloudsql/
│   ├── src/
│   │    └── index.ts
│   ├── cloud_sql_proxy
│   ├── package.json
│   ├── package-lock.json
│   ├── tsconfig.dev.json
│   ├── tsconfig.json
├── .firebaserc
└── firebase.json

Cloud SQL Auth Proxyを立ち上げます。

$ ./cloud_sql_proxy -dir=cloudsql -instances=myproject:myregion:myinstance

functions/cloudsql/内にmyproject:myregion:myinstanceと同名のファイルができるはずです。
その状態で、別コンソールからfunctionのemulatorを立ち上げます。

$ firebase emulators:start --only functions:myfunction

ハマった

至る所でこれが出まくるのに悩まされました。

$ Error: connect ENOENT /cloudsql/myproject:myregion:myinstance

env.DB_SOCKET_PATH

デプロイ時はprocess.env.DB_SOCKET_PATHにソケットが立つようです。(ちゃんと確かめてないですが多分"cloudsql"とかだと思います)
ローカルでの実行ではその環境変数がないので、/cloudsqlを指定しておきます。
TypeORMを使っているのでentitiesとかありますが、他のサービスでも基本同じ感じです。socketPathが大事。

datasource.ts
const dbSocketPath = process.env.DB_SOCKET_PATH || "/cloudsql";
export const AppDataSource = new DataSource({
    type: "mysql",
    socketPath: `${dbSocketPath}/myproject:myregion:myinstance`,
    username: *******, // ここら辺も
    password: *******, // 適宜
    database: *******, // 変えてください
    entities: [
        "./build/entity/**/*.js"
    ],
})

まとめ

  • デプロイ時のルートはfunctions直下
  • デプロイ時は process.env.DB_SOCKET_PATHにソケットが立つ

Discussion