Help us understand the problem. What is going on with this article?

Expressで作ったAPIをaws-serverless-expressでサーバレス化した話

More than 1 year has passed since last update.

はじめに

最近Expressで作ったAPIを、aws-serverless-expressを使ってサーバレス化したときの手順をまとめる。

今回はExpressをサーバレス化する話なので、Expressを使ったAPIの構築については触れない。

前提

  • Expressで既にAPIを作っている
  • AWSアカウントを持っている
  • aws-cliが設定済みである

aws-serverless-expressとは

awslabが出してる、Expressで作ったRESTful APIをサーバレス化するツール。
サーバレスAPIは、Express + Lambda + API Gatewayを用いて構築する。

このツールの凄いところは、アプリケーションでいじるところが殆ど無いところだ。
なので、既にExpressでAPIサーバを構築している人なら、少しの手順を踏むだけで、サーバレスなAPIを簡単に構築することができる。

細かいことはGithubのREADMEに書いてある。
天下のAWSさんが出しているだけあって、exampleもちゃんとしてる。
1からAPIを作る人はexampleをコピーするところから始めると良いと思う。

Githubのリンクはこちら

サーバレス化

1. aws-serverless-expressのインストール

以下を実行して、aws-serverless-expressをインストール。

$ npm install --save aws-serverless-express

2. exampleのpackage.jsonのscriptsをコピー

aws-serverless-expressのexampleには、既に便利なscriptが用意されているため、今回はそれを利用する。

自分のプロジェクトのpackage.jsonに以下をコピペする。
(Windows以外の人はwin-config以下はコピペする必要なし)。

  "scripts": {
    "start": "node app.local.js",
    "config": "node ./scripts/configure.js",
    "deconfig": "node ./scripts/deconfigure.js",
    "local": "node scripts/local",
    "invoke-lambda": "aws lambda invoke --function-name $npm_package_config_functionName --region $npm_package_config_region --payload file://api-gateway-event.json lambda-invoke-response.json && cat lambda-invoke-response.json",
    "create-bucket": "aws s3 mb s3://$npm_package_config_s3BucketName --region $npm_package_config_region",
    "delete-bucket": "aws s3 rb s3://$npm_package_config_s3BucketName --region $npm_package_config_region",
    "package": "aws cloudformation package --template ./cloudformation.yaml --s3-bucket $npm_package_config_s3BucketName --output-template packaged-sam.yaml --region $npm_package_config_region",
    "deploy": "aws cloudformation deploy --template-file packaged-sam.yaml --stack-name $npm_package_config_cloudFormationStackName --capabilities CAPABILITY_IAM --region $npm_package_config_region",
    "package-deploy": "npm run package && npm run deploy",
    "delete-stack": "aws cloudformation delete-stack --stack-name $npm_package_config_cloudFormationStackName --region $npm_package_config_region",
    "setup": "npm install && (aws s3api get-bucket-location --bucket $npm_package_config_s3BucketName --region $npm_package_config_region || npm run create-bucket) && npm run package-deploy",
    "win-config": "npm run config",
    "win-deconfig": "npm run deconfig",
    "win-local": "npm run local",
    "win-invoke-lambda": "aws lambda invoke --function-name %npm_package_config_functionName% --region %npm_package_config_region% --payload file://api-gateway-event.json lambda-invoke-response.json && cat lambda-invoke-response.json",
    "win-create-bucket": "aws s3 mb s3://%npm_package_config_s3BucketName% --region %npm_package_config_region%",
    "win-delete-bucket": "aws s3 rb s3://%npm_package_config_s3BucketName% --region %npm_package_config_region%",
    "win-package": "aws cloudformation package --template ./cloudformation.yaml --s3-bucket %npm_package_config_s3BucketName% --output-template packaged-sam.yaml --region %npm_package_config_region%",
    "win-deploy": "aws cloudformation deploy --template-file packaged-sam.yaml --stack-name %npm_package_config_cloudFormationStackName% --capabilities CAPABILITY_IAM --region %npm_package_config_region%",
    "win-package-deploy": "npm run win-package && npm run win-deploy",
    "win-delete-stack": "aws cloudformation delete-stack --stack-name %npm_package_config_cloudFormationStackName% --region %npm_package_config_region%",
    "win-setup": "npm install && (aws s3api get-bucket-location --bucket %npm_package_config_s3BucketName% --region %npm_package_config_region% || npm run win-create-bucket) && npm run win-package-deploy"
  }

次に、exampleで使用しているscriptファイルや、yamlファイルをコピーする必要がある。
プロジェクトルートで以下を実行。

$ git clone https://github.com/awslabs/aws-serverless-express.git ase
$ cp -r ase/example/scripts .
$ cp ase/example/api-gateway-event.json .
$ cp ase/example/cloudformation.yaml .
$ cp ase/example/lambda.js .
$ cp ase/example/simple-proxy-api.yaml .
$ rm -rf ase

3. awsアカウントとs3バケットの設定

先程コピーしたスクリプトを使用して、awsアカウントとs3バケットの設定を行う。

$ npm run config -- \
--account-id="<accountId>" \
--bucket-name="<bucketName>" \
--region="<region>" \            # optinal
--function-name="<functionName>" # optinal

このコマンドの実行が成功すると、以下の3つのファイルが書き換わる。

  • package.json
  • simple-proxy-api.yaml
  • cloudformation.yaml

4. app.jsの修正

Expressをaws-serverless-expressで動かすには少しコードに手を加えなくてはならない。

まず、app.jsでaws-serverless-expressのMiddlewareを有効化する必要がある。
以下をapp.jsに追加

const express = require('express')
+ const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')

const app = express()

+ app.use(awsServerlessExpressMiddleware.eventContext())

次に、aws-serverless-expressではUNIXドメインソケットで別の箇所でlistenしているらしいので、app.jsに書いてるlistenメソッドは削除する必要がある。

- app.listen()

最後に、lambda.jsでapp.jsを読み込む必要があるため、app.jsをmodule化する必要がある。

以下の一文をapp.jsの末尾に追加

+ module.exports = app

5. lambda.jsの修正

exampleからコピーした、lambda.jsを修正する。
先程修正したapp.jsのパスを指定して、importするだけで良い。

const awsServerlessExpress = require('aws-serverless-express')
- const app = require('./app')
+ const app = require('./path/to/app')

6. デプロイ

exampleで用意されているsetupスクリプトを実行するだけで良い。

$ npm run setup

setupスクリプトを実行すると以下が順番に実行される。

  1. npm install
  2. デプロイ先のs3バケットの作成
  3. CloudFormationのテンプレートの作成
  4. CloudFormationのデプロイ

3. で生成されるCloudFormationのテンプレートはpackaged-sam.yamlというファイルに出力される。
packaged-sam.yamlの内容は以下の通り

  1. API Gatewayの構築
  2. Lambda Functionの作成
  3. Lambdaの実行権限のあるIAMロールの作成

setupスクリプトの実行が成功していれば、CloudFormationのStackが実行されているはずなので、AWSコンソールにログインして、CloudFormationが実行されているか確認する。

7. 確認

AWSコンソールにサインインし、API Gatewayサービスを選択。
新しくAPIが作成されていることを確認する。

新しく作成されたAPIを選択し、「ステージ > prod > URLの呼び出し」に書かれているURLをBase URLとしてAPIを叩いてみる。

Expressで予め作成したAPIを実行して、動くことを確認する。
以下は例。

$ curl http://hogehoge.execute-api.ap-northeast-1.amazonaws.com/prod/v1/fuga

まとめ

Expressを使って既に動いているAPIを、たった7つのステップで、簡単にサーバレス化できてしまった。

これからサーバレス、マイクロサービスがトレンドになる中、簡単に既存のAPIをサーバレス化できてしまう仕組みは本当に凄いと思った。流石AWSさん。

API Gatewayの作成まではできたので、後は独自ドメインにしたりhttpsを有効化したり、色々カスタマイズすると良いと思う。
自分はめんどくさがって手動でポチポチ設定してしまったが、本当はこの辺もCloudFormationでできるはずなので、暇になったら設定してみる。

leverages
インターネットを事業軸に、IT、医療、その他新規分野に30を超える自社メディア事業を展開しています。
https://leverages.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away