Ishida-IT LLC

< Back

Google Cloud Runで動くNode.jsアプリケーションを開発する(3)Cloud SQL

Posted: 2020-07-27


  1. ローカル開発環境でNode.jsアプリケーションを作成する
  2. アプリケーションをコンテナ化し、Cloud Runにデプロイする
  3. Gitからの継続的デプロイを設定する
  4. Cloud Translation APIに接続する
  5. Cloud SQL上のMySQLデータベースに接続する
  6. Googleアカウント認証を追加する
  7. フロントエンド部分をFirebase Hostingに移行する



5. Cloud SQL上のMySQLデータベースに接続する

MySQLインスタンスを作成

マシンタイプは、一時的なテスト目的であれば最小の「db-f1-micro」でも大丈夫です。

MySQLのユーザを作成

アプリケーションからデータベースに接続するためのユーザを作成します。



データベースを作成

次にデータベースを作成します。ここではCharacter setは「utf8mb4」、Collationは「utf8mb4_bin」としておきました。



データベースに接続

デフォルトではCloud SQLのデータベースには外部からのアクセスが許可されていません。ローカル開発環境から接続するには、Cloud SQL Proxy を使います。

gcloudコマンドで認証が完了していればCloud SQL Proxyはそのクレデンシャルを使ってCloud SQLインスタンスに接続し、localhostへの接続要求を中継します。

Cloud SQL Proxyのページから実行ファイルをダウンロードして任意のフォルダに保存してください。

> /foo/bar/cloud_sql_proxy -instances=[プロジェクトID]:[リージョン]:[SQLインスタンスID]=tcp:3306

を実行すると任意のMySQLクライアントからlocalhost:3306経由でCloud SQLインスタンスに接続できる状態になります。

次の画像はMySQL Workbenchを使って接続した例です。



テーブルを作成

Cloud SQL上のデータベースに接続できたら、次のSQLを実行してwordsテーブルを作成しておきます。

ついでにいくつかサンプルのレコードも挿入しておきましょう。

CREATE TABLE `words`.`words` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `ja` NVARCHAR(200) NOT NULL,
  `en` NVARCHAR(200) NOT NULL,
  `es` NVARCHAR(200) NOT NULL,
  `fr` NVARCHAR(200) NOT NULL,
  `done` TINYINT NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`));

INSERT INTO `words`.`words` (`ja`, `en`, `es`, `fr`, `done`) VALUES 
    ('今日', 'today', 'hoy', "aujourd'hui", 0);
INSERT INTO `words`.`words` (`ja`, `en`, `es`, `fr`, `done`) VALUES 
    ('明日', 'tomorrow', 'mañana', "demain", 0);
INSERT INTO `words`.`words` (`ja`, `en`, `es`, `fr`, `done`) VALUES 
    ('自転車', 'bicycle', 'bicicleta', "vélo", 0);

今回のサンプルアプリケーションでは、各行に日本語、英語、スペイン語、フランス語の4ヶ国語を保存できるようになっています。




ローカルで動くNode.jsアプリケーションからCloud SQLに接続する

アプリケーションからデータベースに接続するために、mysqlとKnexというパッケージをインストールしておきます。

> npm i mysql knex

次に database.js ファイルを作成します。

database.js

const Knex = require('knex');
const connect = () => {
  const config = {
    user: process.env.DB_USER,
    password: process.env.DB_PASS,
    database: process.env.DB_NAME,
    host: process.env.DB_HOST,
    socketPath: process.env.DB_SOCKET,
  };

  return Knex({
    client: 'mysql',
    version: '5.7',
    connection: config,
  });
};
const knex = connect();
module.exports = knex;

index.jsでdatabase.jsをインポートし、単語一覧を返すAPIエンドポイントを作成します。

index.js

...
const knex = require('./database');
...

// 単語一覧
app.get('/words', async (req, res) => {
  const words = await knex.select('*').from('words').orderBy('id');
  res.json({ status: 'ok', data: [...words] });
});

database.jsで新たに5つの環境変数を参照しているので、それらをアプリケーション起動時にセットします。

ここでは変数ごとに export する方法に代えて.envファイルに変数名と値を記述する方法を使います。

.env

GOOGLE_APPLICATION_CREDENTIALS=/xxx/xxxxxxxxxx.json
DB_USER=xxxxxx
DB_PASS=xxxxxx
DB_NAME=words
DB_HOST=localhost
DB_SOCKET=
.envはソース管理の対象外とするために.gitignoreに追加することを忘れないようにしてください。

ローカル開発環境ではUnixソケットは使わないのでDB_SOCKETは空白で構いません。逆にCloud上で動く本番環境ではDB_HOSTを空白にしてDB_SOCKETに値をセットします。

.envの内容をアプリケーションから参照できるようにするために、dotenvパッケージをインストールします。ただしこれはローカル開発環境でしか使わないので、-Dオプションを付けておきます。

> npm i -D dotenv

さらに package.jsonを少し編集します。

...
  "scripts": {
    "dev": "node -r dotenv/config src/index.js",
    "start": "node src/index.js"
  },
...

これで、

> npm run dev

を実行すると.envファイルの内容が環境変数にセットされた状態でアプリケーションが起動するようになります。

アプリケーションを再起動した後、ブラウザで http://localhost:8080/words を開くと単語一覧のJSONが返って来ているのが確認できます。

ここまでで、ローカル開発環境からCloud SQL上のMySQLデータベースに接続できるようになりました!



Cloud RunからCloud SQLに接続する

まずはCloud SQL Admin APIを有効にする必要があります。詳細は下のドキュメントを参照してください。

Cloud Run(フルマネージド)から Cloud SQL に接続する

この時点で一旦GitHubにプッシュしてCloud Run上でも正しくデータベースに接続できるか、試しておきましょう。

前回の記事でGitからの継続的デプロイを設定したので、プッシュすると自動でビルドが始まり新しいコンテナがデプロイされますね。

デプロイ完了後にURLの末尾に /words を付けて単語一覧のAPIを呼んでみましょう。

エラーになりました。このエラーは、Cloud Run上でDB接続の設定が正しくされていないために発生しています。

Cloud Runの管理画面でデプロイ設定に環境変数を追加しましょう。

「EDIT & DEPLOY NEW REVISION」をクリックしてください。

「VARIABLES」タブを開いて、DB_USER, DB_PASS, DB_NAME, DB_SOCKET の4つの変数をセットします。DB_HOSTは空白にしておくか、もしくは変数の追加自体を省略します。

次に、「CONNECTIONS」タブで接続先のCloud SQLインスタンスを指定します。これを忘れると接続できないので注意してください。

この「VARIABLES」と「CONNECTIONS」で設定した内容は、次回以降のデプロイ時にも保持されていますので、一度だけ設定すれば大丈夫です。

ではDEPLOYをクリックしてデプロイします。デプロイ完了後、再度 {デプロイ先URL}/words にアクセスしてみましょう。

正しくJSONが返って来ていますね。これでCloud RunからCloud SQLへの接続ができました!


次回はGoogleアカウント認証を追加して、いよいよ「4ヶ国語対応単語帳アプリケーション」を完成させます。





参考URL:

Cloud Run local development - YouTube