Twilio CLI(サーバーレス開発編)


はじめに

みなさん、こんにちは。
KDDIウェブコミュニケーションズのTwilio事業部エバンジェリストの高橋です。

前々回の「Twilio CLI(セットアップ編)」、前回の「Twilio CLI(API操作編)」に続いて、最後はTwilio CLIでサーバーレスの開発を行うための方法をご紹介します。本題に入る前に、まずはTwilioのサーバーレスについて簡単に説明します。
Twilioでは、電話の操作をするためにTwiMLというマークアップ言語を使います。以前は、このTwiMLを生成したり、ホストするために外部のサーバーを連携させる必要があったのですが、現在は外部のサーバーを用意しなくても、Twilio内部でTwiMLをホストしたり、生成することが可能になっています。
これはたとえば以下のような機能になります。

TwiML Bins

Twilioの管理コンソールを使って、Twilioの内部に直接TwiMLをホストする機能です。管理コンソール上で直接TwiMLを記述することができるので、スタティックなTwiMLを返す場合に便利です。

Twilio Assets

Twilioが持つストレージサービスです。mp3ファイルのようなTwiMLから呼び出しが行われるファイル以外にも、HTMLファイルやJavaScriptファイル、CSSファイルなどもホストすることができ、それぞれにパブリックなURLが払い出されるため、Webサーバーとしてコンテンツを表示するなども可能になります。
パブリックなURLを払い出す方法だけでなく、外部からはアクセスできずFunctionsからのみアクセス可能なプライベートな保存も可能です。

Twilio Functions

Twilio Functionsは、Twilioが提供するFaaS(Functions as a Service)です。Node.jsという言語のコードをTwilio上に直接記述することで、そのコードを実行する役割を持ちます。エンジニアはサーバーを意識することなく、コードだけに集中することができ、かつ月に10,000回までの実行が無料です(10,001回目からも非常に安価です)。
動的にTwiMLを生成することはもちろん、外部のWebサービスと連携したり、多岐にわたった処理を実行することができます。

このようにTwilioには便利な機能が用意されているのですが、従来の欠点は、これらの機能が管理コンソールからしか扱えないということでした。たとえば、Assetsにファイルをアップロードするのも管理コンソールから手動で行う必要がありますし、Functionsのコードを修正するのもすべて管理コンソール経由でした。
開発者の多くは、ローカルPC上でコーディングをしテストをしてからサーバーにデプロイする手法を好みます。これを実現するのが、今回ご紹介するTwilio CLI Serverless Pluginになります。

Twilio CLI Serverless Pluginとは

Twilio CLI Serverless Pluginは、その名の通りTwilio CLIのプラグインになります。Twilio CLIにはプラグイン機能があり、Twilioが提供するいくつかのプラグインだけでなく、自分自身でプラグインを作ることもできます。
Serverless Pluginを使うことで、以下のことが可能になります。

  • ローカルPC上にTwilioの開発環境を構築することができます。
  • 開発したFunctionsをローカルで実行したり、デバッグすることができます。
  • Assets機能をローカルディスク上で実現し、Functionsから読み込むこともできます。
  • ローカル上で作った実行環境をサーバーにデプロイすることができます。

Serverless Pluginのインストール

Twilio CLIにServerless Pluginをインストールするには、以下のコマンドを利用します。

twilio plugins:install @twilio-labs/plugin-serverless

インストールが終わると、serverlessコマンドが有効になります。

サンプルプロジェクトを作ってみる

ではここから、Serverless Pluginを使ってローカル開発環境を構築してみましょう。

サンプルプロジェクトを作成したフォルダに移動し、以下のコマンドを入力します。

twilio serverless:init first-project

以下のような画面が表示され、自動的にサンプルのプロジェクトが出来上がります。

プロジェクトが完成したら、そのプロジェクトに移動します。

cd first-project

プロジェクトは以下のようなディレクトリ構造を持っています。

./
├── assets
│   ├── index.html
│   ├── message.private.js
│   └── style.css
├── functions
│   ├── hello-world.js
│   ├── private-message.js
│   └── sms
│       └── reply.protected.js
├── node_modules
├── package-lock.json
└── package.json

assetsフォルダ

こちらには、3つのファイルがあります。この内、message.private.jsのように、拡張子の直前にprivate.が含まれる場合、このファイルはプライベート(外部からアクセス不可)な状態でデプロイされます。デプロイ時にprivate.は除かれます。

functionsフォルダ

こちらには2つのファイルと1つのフォルダ(sms)が配置され、さらにそのフォルダの中にも1つファイルが生成されているのがわかります。smsフォルダの中にある、reply.protected.jsは、protected.が含まれているため、このFunctionに関しては、外部からアクセス時に認証が必要です(同じアカウント内から読み込む場合は認証は不要です)。

ローカルで実行

以下のコマンドを入力すると、ローカル環境で簡易的なWebサーバーが起動し、その上でFunctionsが動作していることが確認できます。

npm start

起動している状態でブラウザを開き、http://localhost:3000/hello-worldを入力してみると、以下のようなページが表示されるはずです。

また同様に、Assetsに関してもローカルでアクセスが可能になります。同じくブラウザでhttp://localhost:3000/index.htmlと入力してみると、以下のページが表示されます。

終了させるにはctrl-cを入力します。

もしローカルで実行中のFunctionsやAssetsを外部からもアクセスさせたい場合は、ngrokを利用します。
先程のコマンドを実行した後、自分でngrokを起動してもよいですが、以下のコマンドを利用するとngrokの起動までが自動で行えるので便利です。

twilio serverless:start --ngrok=""

ngrokのサブドメインをお持ちの方であれば、最後の""のところに、サブドメインを指定することもできます。

デプロイ

ローカルでの開発が完了したら、いよいよサーバーにデプロイしましょう。
デプロイ作業は簡単です。以下のコマンドを入力するだけで、ローカル環境がデプロイされます。

twilio serverless:deploy

以下のような画面が表示され、しばらくするとデプロイが完了します。

ユニークなドメイン(上記の例ではfirst-product-4106-dev.twil.io)が設定された状態でデプロイが完了していることがわかります。
試しに、Assetsにあるindex.htmlを開いて、先程と同じ画面が表示されることを確認しましょう。

削除

デプロイしたサービスを削除するには、以下の手順を実行します。

現在デプロイされているサービスの一覧を取得する。

twilio api:serverless:v1:services:list

削除したいサービスのSIDを調べたら、以下のコマンドでサーバー上から削除します。

twilio api:serverless:v1:services:remove --sid [削除したいサービスのSID]

最後に、ローカルフォルダ内にある.twilio-functionsというファイルを削除します。
このファイルが残っていると、次回のデプロイ時にエラーが出てデプロイに失敗します。
削除後に再度デプロイしたときは、生成されるAssetsやFunctionsのURLが変更される点にも注意してください。

補足

環境変数

管理コンソールでFunctionsを使ったことがある方はご存知かと思いますが、Functionsでは環境変数が使えます。
Serverless Pluginを使う場合も、同様に環境変数が使えます。
プロジェクトディレクトリに、.envというファイルがありますので、そこに環境変数を指定しておくとデプロイ時にサーバー側に反映されます。デフォルトでは、ACCOUNT_SIDAUTH_TOKENという変数が設定されています。

外部モジュール

Functionsから外部モジュールを使う場合は、通常のNode.jsと同じように、例えばプロジェクトフォルダで以下のようにインストールします。

npm install request-promise --save

こうすることで、プロジェクトフォルダのpackage.jsonに当該モジュールの情報が書き込まれるので、ローカル開発でもデプロイ環境でもモジュールを扱うことができます。

context.getTwilioClient()は使えない

管理コンソールからFunctionsを使う場合、context.getTwilioClient()でTwilio APIにアクセスできるようになりますが、Serverless Pluginを使う場合は残念ながら利用できません。
Severless Plugのテンプレートを作成した際に、.envにACCOUNT_SIDとAUTH_TOKENが生成されていますが、こちらは本来のAccountSidではなく、Serverlessの環境のために動的に生成されたAPIキーになります。
そこで以下のようにコーディングするのが現時点でのベストプラクティスです。

const twilio = require('twilio');

const myAccountSid = 'ACxxxxxxxxxxxxxx'; // アカウントSIDを記載します
const apiKey = context.ACCOUNT_SID; // .envにデフォルトで記載されている値を使います
const apiSecret = context.AUTH_TOKEN; // .envにデフォルトで記載されている値を使います

const client = twilio(apiKey, apiSecret, { accountSid: myAccountSid });

まとめ

今回はTwilio CLIを使って、サーバーレスの開発(FunctionsやAssets)をCLI経由で実現する方法をご紹介しました。


Twilio(トゥイリオ)とは

https://twilio.kddi-web.com
Twilioは音声通話、メッセージング(SMS/チャット)、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウドAPIサービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。