部署Nest.Js至GAE(四):連接cloud sql

前言

使用Nest.Js開發,通常都會相應使用typeOrm連接資料庫
開發時期連接本機資料庫都有相當多的教學,單純、簡單
若是內部系統,有自己的Server,大至上都跟開發時期差不多
但部署到GCP就不一樣了
雖然Cloud SQL也有提供靜態IP,但直接使用他提供的名稱更優

解法其實網路上就有,但要下對關鍵字…
我一開始都用Nest.Js connect cloud sql 等關鍵字來找,就是沒有答案
還想到這到底是多困難
最後想到Nest.Js本質是typeOrm,才找到解法= =…

連線方式

在GCP設定好Cloud SQL後
到其主頁面的連線名稱可以看到project:region:instance

如下範例調整

{
  "name": "default",
  "type": "mysql",
  "extra": {
    "socketPath": "/cloudsql/{project:region:instance}"
  },
  "username": "root",
  "password": "xxxx",
  "database": "yyy",
  "synchronize": true,
  "logging": false,
  "entities": [
    "dist/**/*.entity.js"
  ]
}

參數寫法

Nest.Js/configuration的寫法其實滿少資訊的
分享自己的寫法供參考
開發模式時連接本地DB、部署到GCP時連接Cloud SQL

共會有3個檔案:database.config.tsdatabase.development.yamldatabase.production.yaml
主要是將dev、prod會不同的參數拉至yaml檔
共同且不太會異動的參數寫在ts裡

database.development.yaml

host: 'localhost'
port: 5432
username: 'dev'
password: 'dev'
database: 'demo'
logging: true
synchronize: true

database.production.yaml

host: /cloudsql/{project:region:instance}
extra: 
      socketPath: /cloudsql/{project:region:instance}
username: 'app'
password: 'pwd'
database: 'prod_db'
logging: false
synchronize: false

database.config.ts

import { registerAs } from "@nestjs/config";
import { readFileSync } from 'fs';
import * as yaml from 'js-yaml';
import { join } from 'path';

const YAML_CONFIG_FILENAME = `database.${process.env.NODE_ENV}.yaml`;

export default registerAs('database', () => {
  const yamlConfig = yaml.load(
    readFileSync(join(process.cwd(), 'environment', YAML_CONFIG_FILENAME), 'utf8'),
  ) as Record<string, any>;
  
  return {
    retryAttempts: 10,
    retryDelay: process.env.NODE_ENV === 'development' ? 5 * 1000 : 30 * 1000,
    type: 'postgres',
    entities: [`dist/**/*.entity.js`],
    logger: 'file',
    autLoadEntities: true,
    ...yamlConfig
  };
});

後記

我當初照著輸入時仍一直連線失敗,gcloud部署一次又要2~3分鐘
重新部署了N次才發現,我yaml寫錯了….

因為我有使用官方的configuration模組,並將參數yaml化
而找到的網路資訊都是jsonts物件

且當初只想快速測試,extra參數很直覺地貼上:

host: /cloudsql/{project:region:instance},
extra: { 
    socketPath: /cloudsql/{project:region:instance}
}

而當初又尚未連接 cloud logging,故當時完全不知錯誤原因
Nest.Js一執行,parse yaml時就直接噴錯了,根本執行不了
而且還很白痴的host連最後面的,一起複製上去= =

明明是件很簡單的事情,卻也卡了我2、3小時-.-

參考資料

stack overflow / Typical ormconfig.json file for Google Cloud SQL?

系列文章

部署Nest.Js至GAE系列文章