Alternative Architecture DOJO

オルターブースのクラウドネイティブ特化型ブログです。

Node.js製のヘッドレスCMSの "strapi" をAzureにいい感じにデプロイできるように試してみた

f:id:tech-tsubaki:20191204181346p:plain

こんにちは。MLBお兄さんこと松村です。
この記事はオルターブース Advent Calendar 2019の5日目の記事です。

adventar.org

4日目の記事は知念さんのノンコーディングでIoTを楽しむ話でした。

aadojo.alterbooth.com

さて、今回のテーマはタイトルにある通り「strapi」です。このツールをご存知でしょうか?私は密かに気になっていました。

strapiとは?

strapiとはNode.jsで作られたヘッドレスCMSです。

strapi.io

WordPressに代表されるCMSはフロントエンド機能もバックエンド機能も有し、オールインワンでサーバーにデプロイする形が一般的です。
しかし、strapiはCMSに必要なバックエンドAPIのみを提供しているため、フロントエンドは自分で用意することとなります。

つまり「SPA(Single Page Application) + strapi」というような構成でCMSを開発することができます。
WordPressを使うとしても、ページの見た目(UI)はサイトの種別や目的に応じてカスタマイズするケースが多いですよね。

なお本記事ではstrapiのセットアップには言及しません。こちらの記事で詳しく説明されていますのでリンクを載せておきます。

www.hivelocity.co.jp

strapiをMicrosoft Azureにデプロイする

strapiの公式ドキュメントでは、デプロイ先としてDockerやAWS、Herokuなどの手順が用意されています。
そのため本記事では、Microsoft Azureにデプロイしようとするときに使うサービスや手順をまとめてみます。

サンプルアプリケーション

公式ドキュメントのQuick Start Guideに沿って作ったアプリケーションはこちらになります。

github.com

Azure WebApps for Containersにデプロイする

strapiはデプロイするだけでは実行されず、起動用のコマンド(例えば yarn start)を実行する必要があります。
そのため今回はコンテナーイメージを用意して、Azure WebApps for Containersにデプロイします。

Dockerfileを用意する

公式ドキュメントのコンテナーに展開する手順はさらっとした内容になっているため、GitHubのほうが詳しく記載されています。

github.com

strapiが用意しているコンテナーイメージは2種類あります。

  • strapi/strapi ... strapiプロジェクトを作成するときやプロジェクトを実行するときに使う
  • strapi/base ... strapiプロジェクトをビルドするときに使う

Dockerのマルチステージビルドの機能を使って、このようなDockerfileを作りました。

FROM strapi/base:12-alpine as base
WORKDIR /srv/app
COPY package.json /srv/app
COPY yarn.lock /srv/app
RUN yarn install
COPY . .
RUN yarn build && yarn --development

FROM strapi/strapi:3.0.0-beta.17.6-alpine
WORKDIR /srv/app
COPY --from=base /srv/app .
EXPOSE 1337
CMD ["yarn", "start"]

あまり情報がありませんでしたが、こちらの記事を参考にしてDockerfileを作ることができました。

strapi.io

コンテナーレジストリにプッシュする

上記のDockerfileを使って、アプリケーションを含めたコンテナーイメージを作成しましょう。
作成したコンテナーイメージはDocker CLIAzure CLIを用いて、Azure Container Registry (ACR)にプッシュしておきます。

docs.microsoft.com

コンテナーイメージをビルドする

docker build -t strapi-tutorial:latest .

Azureにログインする

az login

コンテナーイメージをACRにプッシュする

az acr login -n myregistry
docker tag strapi-tutorial:latest myregistry.azurecr.io/strapi-tutorial:latest
docker push myregistry.azurecr.io/strapi-tutorial:latest

※ACRのリソース名は適宜読み替えてください。

f:id:tech-tsubaki:20191201213054p:plain

WebApps for Containersにデプロイする

ようやくコンテナーイメージが用意できたのでWebApps for Containersにデプロイします。
さくっとやるにはACRのコンテナーイメージのタグの横にある「...」の「Webアプリにデプロイ」をクリックして、WebApps for Containersのリソースを作成します。

f:id:tech-tsubaki:20191201213110p:plain

リソースが作成されてコンテナーイメージのpullまで完了すると、strapiにアクセスすることができます。
ちなみにstrapiには日本語の管理画面が用意されており、セットアップとして管理者ユーザーの作成から始まります。

f:id:tech-tsubaki:20191201213124p:plain

Application Insightsに接続する

これまでの手順でstrapiをAzure上で実行することができました。
次はstrapiにAzure Application Insightsを組み込んで、アプリケーションの監視をAzureで行えるようにします。

ここで必要な一連の作業はこのコミット履歴から見ることができます。

github.com

SDKをインストールする

公式ドキュメントにNode.js用の手順も用意されていますので、こちらに沿って進めます。

docs.microsoft.com

npm install applicationinsights --save

ライブラリを読み込んでテレメトリを送信する

私のApplication Insightsの使い方の一つとして、アプリケーション内のログメッセージをApplication Insightsに送信する使い方があります。
今回は例としてミドルウェアを一つ用意して、そのなかでテレメトリを送信してみます。

ミドルウェアを作成する

strapiにミドルウェアを作成するにはこちらのドキュメントを参考にします。慣れるまではちょっと難しいですね。

strapi.io

config/middleware.json にミドルウェアを追加する

{
  "timeout": 100,
  "load": {
    "before": [
      "responseTime",
      "logger",
      "cors",
      "responses",
      "gzip",
      "appInsights" ←これ
    ],
    "order": [
      "Define the middlewares' load order by putting their name in this array is the right order"
    ],
    "after": [
      "parser",
      "router"
    ]
  }
}

config/environments/{environment}/middleware.json を作成する

{environment} はstrapiを実行する際の環境(production/staging/development 等)を指定します。
各環境で有効にするミドルウェアを middleware.json に記載します。

{
  "appInsights": {
    "enabled": true
  }
}

ミドルウェアファイルを作成する

ミドルウェア本体となるファイルを作成します。今回は middlewares/appInsights/index.js というファイルを作成します。
なおコード中の "<your instrumentation key>" は自身が用意したApplication Insightsのインストルメンテーションキーに置き換えてください。

module.exports = strapi => {
    return {
        initialize() {
            strapi.app.use(async (ctx, next) => {
                const appInsights = require("applicationinsights");
                appInsights.setup("<your instrumentation key>");
                appInsights.start();
                strapi.log.debug('app insights started');

                const client = appInsights.defaultClient;
                client.trackTrace({message: "trace message"});

                await next();
            });
        },
    };
};

動作を確認してみる

今回はミドルウェアでテレメトリを送信するようにしたので、HTTPリクエストを受けるたびに送信します。
Application Insightsのポータルを確認すると、きちんとテレメトリが送信されていることがわかります。

f:id:tech-tsubaki:20191201221818p:plain

続きはまた次回

今回はアプリケーションサーバーやログにフォーカスして、どうやってAzureにデプロイするかを試してみました。
書ききれなかったものもあるので続きはまた別の記事をお楽しみに!

adventar.org