1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TypeORMでCloud RunからCloud SQLへ接続する(ソケット接続)

Last updated at Posted at 2022-07-05

はじめに

Node.js+Express(TypeScript)プロジェクトをGoogle Cloud Run で動かしつつ、TypeORMでGoogle Cloud SQLに接続するするのに少し詰まったため、ポイントを簡単にまとめてみました。

本記事の内容に入る前に公式ドキュメントの「Cloud Run を構成する」のセクションまで行ってください。本記事はこのドキュメント内の「Cloud SQL への接続」と同じ作業をTypeORM向きに書いたものです。

DBエンジンはMySQLを前提としています。
TypeORMについては以下も合わせて参照してください。

結論

TypeORMのDataSourceオブジェクトに渡すオプションに以下を追加し、hostportの2つのプロパティを削除することで、ソケット接続ができました。hostportのいずれか片方でも設定している(undefinedでない)とsocketPathは無視され127.0.0.1:3306を標準値としたIPアドレスでの接続になってしまうようです。

{
  socketPath: `/cloudsql/{Cloud SQLインスタンスの接続名}`,
}

つまり、以下のようにすればOK。(もちろんsocketPath以外の項目は各自の環境に合わせて適切なものにしてください。)

const options: DataSourceOptions = {
  type: "mysql",
  synchronize: true,
  logging: true,
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE,
  entities: [path.join(__dirname, "/entity/*.ts")],
  socketPath: `/cloudsql/{Cloud SQLインスタンスの接続名}`,
};

const dataSource = new DataSource(options);

dataSource.initialize(); // 接続

環境

package.jsonから関係するものだけ抜粋しました。TypeORMはバージョン0.3.6、MySQLドライバーは2.18.1です。

package.json
"dependencies": {
    "@types/express": "^4.17.13",
    "@types/node": "^17.0.41",
    "express": "^4.18.1",
    "mysql": "^2.18.1",
    "ts-node": "^10.8.1",
    "typeorm": "^0.3.6",
    "typescript": "^4.7.3",
  }

Cloud Run から Cloud SQl への接続

公式ドキュメントによれば、ローカルからアクセスする時(ipとポートを指定してhttp接続)と異なりUnix ソケット経由での接続になるようです。

パブリック IP パスの場合は、Cloud Run によって暗号化が行われ、Cloud SQL Auth Proxy を使用して Unix ソケット経由で接続します。

ローカルからCloud SQLへアクセスする場合、SSLを用いていればTypeORMの接続設定は概ね以下のようになっているかと思います。(ユーザー名やPWなどの関係ないプロパティは省略しています。)

const options: DataSourceOptions = {
  type: "mysql",
  host: "123.123.123.123",
  port: 3306,
  ssl: {
    // Cloud SQLのコンソールから発行したSSL接続用の証明書類
    ca: fs.readFileSync(path.join(__dirname, "/server-ca.pem")),
    cert: fs.readFileSync(path.join(__dirname, "/client-cert.pem")),
    key: fs.readFileSync(path.join(__dirname, "/client-key.pem")),
  }
 //...ユーザー名やPWなど
}

しかしCloud Run内からのアクセスの場合、SSLに必要な証明書類を持っていくことなくセキュアな環境でソケット接続によって通信が可能になっているようです。
ソケット通信を利用するために、TypeORMの設定(DataSourceOptions)を以下のように書き換えてください。
hostportの2つのプロパティを削除(undefined)にしておくのがポイントです。これらに値が入ったままだとソケット接続になりません。sslundefinedにしておきましょう。

const options: DataSourceOptions = {
  type: "mysql",
  socketPath: `/cloudsql/{Cloud SQLインスタンスの接続名}` // 追加
 //...ユーザー名やPWなど
};

Cloud SQLインスタンスの接続名

Cloud SQLインスタンスの接続名はCloud SQLの管理画面に出てくる「このインスタンスとの接続」の「接続名」の部分に置き換えてください。
image.png

最後に

ググっていると、以下のようにextendsにネストさせないとダメという情報を見かけましたが、バージョン0.3.6の時点ではその必要は無いようです。

const options: DataSourceOptions = {
  extends:{
    socketPath: `/cloudsql/${process.env.DB_HOST}`,
  }
}

TypeORMのソースを見たところ、DataSourceOptions(共用体型/union)のうち1つであるMysqlConnectionOptionsの継承元のMysqlConnectionCredentialsOptionssocketPathというプロパティがちゃんと定義されていました。

ソースはこちら。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?