前述の通り typeorm + sqlite3 で Azure Web App Service 上ではうまく動作させることが出来ませんでした。そこで、 Azure Database for MySQL サーバーを準備して動作できるか、を確認しました。
これにもちょっと手間取ったのでここに記録として残しておきます。すでに知っている人には当たり前のことばかりかなとは思います。動作を優先させるため、セキュリティ的にちょっと不味いところはあるかもしれません。
以降は Azure で MySQL サーバーは用意済み、管理者の接続も出来ているという前提で書いています。
Windows で mysql コマンドだけ使いたいと思ったとき、ツールのみというパッケージはなかったので、Azure 上の Cloud Shell で実行しています。コマンドの紹介は全て、このシェルで実行していました。
Azure MySQL サーバーの設定
まずは接続を受け付けるようにするため、Azure の管理画面で以下のように設定を行いました。
- Azure サービスへのアクセスを許可:はい
- 自分のIPアドレスからの操作を受け付けるようにするため、IPをルールに登録
- SSL設定 : 無効
SSL 設定は有効にしたいところですが、まずは動作を優先させていきます。
データベース作業用のユーザーの作成
データベースとしては studydb1 というものを用意して、これを操作するユーザーを以下のように追加&権限設定を行いました。
mysql> create user 'sampleuser'@'%' identified by 'password';
mysql> grant all privileges on studydb1.* to 'sampleuser'@'%';
mysql> flush privileges;
ログイン出来ることを確認
この設定が終わった後、シェルからこのユーザーを用いて mysql へ接続できることを確認しておきましょう。
mysql -h サーバーのアドレス -u sampleuser@サーバー名 -p
ここでのポイントはユーザー名です。サーバーのアドレス hogehoge.mysql.database.azure.com といったものの場合、ユーザー名には先ほど指定したものだけでなく、サーバーの名前も付与する必要があるという点です。この場合では、 sampleuser@hogehoge というユーザー名を使います。
このユーザー名の設定の仕方は、他の部分でも同様です。 sampleuser 単体ではなくサーバー名が必要になるので忘れないようにしましょう。
忘れると一見、ユーザーが存在するのに接続できない状態となり混乱します。
typeorm の設定
typeorm の設定として、 ormconfig.json を編集します。基本的に typeorm の mysql を用いるタイプでの設定になっています。注意すべき点はユーザー名で、サーバー名が付いたユーザー名を使うようにします。これを忘れると接続が出来ずエラーが発生します。
{
"type": "mysql",
"host": "hogehoge.mysql.database.azure.com",
"port": 3306,
"username": "sampleuser@hogehoge",
"password": "password",
"database": "studydb1",
"synchronize": true,
"logging": false,
"entities": [
"src/entity/**/*.js"
],
"migrations": [
"src/migration/**/*.js"
],
"subscribers": [
"src/subscriber/**/*.js"
],
"cli": {
"entitiesDir": "src/entity",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
接続に失敗すると、 typeorm から Error: UNKNOWN_CODE_PLEASE_REPORT: An internal error has occurred. Please retry or report your issues. というエラーメッセージが表示されたりします。このときには設定が間違っていないか、ユーザー情報でログインできるかなどを確認するのがよいでしょう。
これで、migration:run を実行してみて正常に動作するか確認してみるとよいでしょう。
デプロイ時の課題
実はこのまま App Service にデプロイしても接続設定が見つけられずエラーになりました。原因が不明ですが、 ormconfig.js や ormconfig.json らを読み込みに失敗しているかの動きです。SSH のシェルでポート番号を変えて起動してみても同様で、それでもローカルの環境では動くという差異が出たままです。
諦めかけていたのですが、別の方法でなんとか稼働させることが出来たのでそれを紹介します。ormconfig.json で設定できるならそれがいいんですけどね。
createConnection の関数で引数に設定情報を渡す方法で対処しました。サンプルのコードは以下の通りです。一応これでデプロイしたものが動作はしています。
createConnection(
{
type: "mysql",
host: "hogehoge.mysql.database.azure.com",
port: 3306,
username: "sampleuser@hogehoge",
password: "password",
database: "studydb1",
synchronize: true,
entities: ["build/entity/**/*.js"],
migrations: ["build/migration/**/*.js"],
subscribers: ["build/subscriber/**/*.js"],
}
)
.then(async (connection) => {
console.log("Inserting a new user into the database...");
const user = new User();
この方法の欠点は ormconfig.json を完全には無くせないことです。 npx typeorm migration:run
などの実行では ormconfig.json を必要とします。
対策するとしたら createConnection
で渡す設定情報を ormconfig.json から読み込んで生成するとかでしょうか。
まとめ
以前の Express + Typeorm を Azure Web App Service にデプロイする流れでは、思ったよりも手間取ることがあったなという印象です。この流れで仕方なく(?) MySQL のサーバーの準備となったわけですが、MySQL には無料プランはないようなので試す場合には最初の1年間の期間でクレジットがある状態で実験するのがよさそうです。
今回使った Cloud Shell も Azure Storage を使用するので、それと MySQL サーバーの分で無料期間後は多少利用料金が課金されそうです。