LoginSignup
0
0

More than 3 years have passed since last update.

AWS SAM CLI Layerを使ってビルド高速化

Last updated at Posted at 2021-02-06

問題

  • ビルドする時のnpm installが重い。

解決

  • 依存モジュールはLayerとして切り出し。
  • Lambda関数側は依存モジュールをdevDependenciesに入れてエディタ上はパスを通す (ビルドするとdevDependenciesはnode_modulesに入らないから、デプロイするLambda関数が肥大化する心配はない)。
  • 開発中はキャッシュオプションをつけてLayerのビルドは短縮。 sam build HelloWorldFunction -c

Layerについて

Layerは/opt下に配置されるイメージ。
なのでパスが通っているところにライブラリが置かれれば良い。

例えば、ランタイムがNode.jsの場合は、/opt/nodejs/node_modulesとかにデフォルトでNODE_PATHが通っている。
だから、nodejs/node_modulesにライブラリを落としてLayerとしてデプロイすればよい。
ディレクトリ名がnodejsなのがポイント。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime

SAMの場合は、ローカルディレクトリをLayerとして指定すれば、よしなにビルド、デプロイしてくれる。

使う側

普通にインポート

const { format } = require("date-fns");
exports.lambdaHandler = async (event, context) => {
  try {
    const d = format(new Date(2014, 1, 11), "yyyy-MM-dd");
    console.log("d=" + d);

エディタ上で参照できるようにdevDependenciesに追加する。

$ npm install date-fns lodash --save-dev

layer側

ディレクトリ名はデフォルトではnodejsとしないとだめ。
(多分NODE_PATHを自分で設定すれば別)
ライブラリを落とす。

$ mkdir nodejs
$ cd nodejs
$ npm init
$ npm install date-fns lodash

テンプレート

Layerを定義し、Functionから参照。
ContentUriにローカルディレクトリのパスを記載。
Metadataが無いとLayerをビルドしてくれない。
Importエラーになってハマった。
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-layerversion.html
デフォでやらない理由があるんだろうか。
いろいろカスタマイズはできそう。
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-layers.html

  MyLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      Description: Layer description
      ContentUri: "nodejs/"
      CompatibleRuntimes:
        - nodejs12.x
    Metadata:
      BuildMethod: nodejs12.x

  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get
      Layers:
        - !Ref MyLayer

ビルド

Layerもビルドしている旨表示されます。

$ sam build

ローカル実行

local Layerのイメージを作りだした。

$ sam local invoke HelloWorldFunction
Invoking app.lambdaHandler (nodejs12.x)
MyLayer is a local Layer in the template
Building image..

Layerに入っているライブラリを使えた。成功。

INFO    d=2014-02-11

キャッシュオプションでビルド

キャッシュがヒットするとこうなる。

$ sam build -c

Starting Build use cache
Valid cache found, ...

Layerは修正しないから、キャッシュがヒットするからライブラリ落とすこともなく早い。
直した関数だけCache is invalidになる。

sam build HelloWorldFunction -c

Cache is invalid, running build
...
Valid cache found, copying previously built resources from layer build

キャッシュがヒットしない場合

node_modulesを比較するから、キャッシュがヒットしない場合は、
node_modulesをきれいにする。

$ npm prune

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0