かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Serverless-layers で node_modules を Lambda にデプロイするパッケージから除く

前回までのあらすじ

TypeScript な Express アプリを aws-severless-express で Serverless 化して AWS にデプロイする所までできました。
しかしデプロイしたパッケージ (zip) には node_modules のファイルが含まれており、サイズが巨大なものになっていました。

serverless-layers で node_modules を Lambda にデプロイするパッケージと分離する

Lambda Layers

Lambda Layersとは、複数のLambda関数で外部ライブラリやビジネスロジックを共有できる仕組みです。
使用するライブラリや共通のビジネスロジックをZIPアーカイブし、Layerに追加することができます。 デプロイパッケージの容量を少なくすることができるためLambdaのソースコードの管理が楽になります。 また依存関係をインストールしてパッケージ化する際に発生するエラーを回避することや、ライブラリのビルドの手順を省くこともできます。
cf. AWS Lambda Layersでライブラリを共通化 - Qiita

serverless-layers の導入方法

  1. Lambda Layers をデプロイする S3 バケットを作成
  2. serverless-layers パッケージのインストール
  3. serverless.yml に設定を追加
  4. デプロイ

1. Layers をデプロイする S3 バケットを作成

AWS コンソールにアクセスして S3 に適当なバケットを作成
作成したバケット名を控えておく。 アクセス権限などはデフォルトのままでOK。

2. serverless-layers のインストール

$ npm install --save-dev serverless-layers

cf. Serverless Layers

3. serverless.yml に設定を追加

serverless.yml

plugins:
  - serverless-webpack
  - serverless-offline
+  - serverless-layers

custom:
  webpack:
    webpackConfig: 'webpack.serverless.config.js'
-    includeModules: true
+  serverless-layers: 
+    layersDeploymentBucket: S3_BUCKET_NAME

serverless-layers が node_modules を分離するので、webpack で externals: [nodeExternals()] する為にモジュールを組み込むようにしていた includeModules: true の指定は削除。(この指定があると Layers に node_modules がアップロードされた上で、node_modules が含まれたパッケージが Lambda にデプロイされてしまいました)

S3 のバケット名を git 管理しないようにする

serverless.yml に直接 S3 のバケット名を書いてしまうと git 管理しているとバケット名がそのまま GitHub に載ってしまったりするので、gitignore したファイルに設定を書いて、${file()} を使って serverless.yml で読み込むようにします。

.gitignore

config/**/*.yml

config/serverless-settings.yml

layersDeploymentBucket: S3_BUCKET_NAME

serverless.yml

custom:
  serverless-layers:
    layersDeploymentBucket: ${file(./config/serverless-settings.yml):layersDeploymentBucket}

4.デプロイ

ここまでの設定ができたら実際に AWS にデプロイしてみます

$ sls deploy --stage prod -v

デプロイが完了したら AWS コンソールから S3 にアクセスすると、Layers 用のバケットに node_modules が zip 化されたファイルがアップロードされ、Lambda 関数で呼び出されるバケットには node_modules が除外されたアプリの zip ファイルがアップロードされていることが確認できます。
そして、API Gateway で表示されるエンドポイントにアクセスすると、express が問題なく動作していることが確認できました。

所感

設定をして deploy すれば自動的に Layers 用のバケットが作られるものだと思っていたので、AWS コンソールから先に S3 バケットを作成しなければならならない部分が解るまでに少し時間がかかってしまいましたが、それ以外は簡単に巨大になりがちな node_modules を分離することが出来てよかったです!

Next Step
  • DynamoDB との接続

[参考]

AWSによるサーバーレスアーキテクチャ

AWSによるサーバーレスアーキテクチャ

  • 作者:Peter Sbarski
  • 発売日: 2018/03/14
  • メディア: 単行本(ソフトカバー)