1.この記事を書こうと思った背景と書いていきたいこと

1-1.背景

  • 先日、Serverless Frameworkがv3にメジャーアップデートされたことは記憶に新しい
  • そんなServerless Frameworkを2系から3系に引き上げてserverless-dotenv-pluginを使って環境変数が読み込もうとしたところ、以下のようなエラーを引いてしまった
$ sls deploy
Environment: linux, node 14.19.0, framework 3.2.0, plugin 6.0.0, SDK 4.3.1
Docs:        docs.serverless.com
Support:     forum.serverless.com
Bugs:        github.com/serverless/serverless/issues

Error:
Cannot resolve serverless.yml: Variables resolution errored with:
  - Cannot resolve variable at "custom.REGION": Value not found at "env" source,
  - Cannot resolve variable at "custom.FAVORITE": Value not found at "env" source
  • このエラーはserverless.ymlと同じ階層のdotenvファイルに書かれた環境が読み込めないというもの
    • 書き方はのドキュメントに詳しく書かれているのでそちらを参照してほしい。ただし、2系で使える書き方であり、3系に対応した書き方はこれから紹介する書き方を採用する必要がある。
    • Serverless Framework: Plugins
  • エラーを引いたときに使ったserverless.yml
    • frameworkVersionを2から3に修正しただけ
service: src

frameworkVersion: '3'
#frameworkVersion: '2'

custom:
  dotenv:
    basePath: ./
  REGION: ${env:REGION}
  nodejsVer: nodejs12.x
  memorySize: 256
  timeout: 900
  TZ: Asia/Tokyo
  FAVORITE: ${env:FAVORITE}

provider:


plugins:
  - serverless-dotenv-plugin
  - serverless-offline

functions:

1-2.この記事で書いていきたいこと

そこで今回は以下2点について書いておきたい。

  • このエラーを解消するためのいくつかの修正方法について
  • またその修正方法は2系と3系どちらでも使うことが出来るのか?あるいはいずれかのバージョンでしか使うことができないか?

2.前提

  • ドキュメントへの反映をするissueがopenであることから記事執筆時点でのやりかたでは動作確認ができたとする。ぜひ、お手元の環境での動作確認をお願いしたい。

  • 修正対象はserverless.ymlのみであり、AWS Lambdaが実行するNode.jsのスクリプトは以下のものを一貫して使う。

    • Node.jsのスクリプトがやっていることは環境変数である、FAVORITE(ここではぼくが好きな音楽アーティストのm-flo)を出力することだけとシンプル
//src/echo.js

'use strict';

module.exports.handler = async (event) => {
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Successfully loading your environment variables as follows;\n my favorite is ' + process.env.FAVORITE,
        input: event,
      },
      null,
      2
    ),
  };
};

3.環境情報

$ grep VERSION= /etc/os-release 
VERSION="20.04.3 LTS (Focal Fossa)"
$ sls --version
Framework Core: 3.2.0
Plugin: 6.0.0
SDK: 4.3.1
$ npm --version
6.14.16
$ nodejs --version
v10.19.0

4.Serverless Framework 3.xでserverless-dotenv-pluginを使って環境変数を読み込む方法

4-1.PRで紹介されているserlverless.ymlの書き方

  • ただし2系では使えなかったので3系のみ対応しているっぽい

# https://github.com/neverendingqs/serverless-dotenv-plugin/discussions/155#discussioncomment-1347632
useDotenv: true ## <-- これが必要

custom:
# https://github.com/neverendingqs/serverless-dotenv-plugin/pull/183#issue-1103321592
  REGION: ${env:REGION}
  FAVORITE: ${env:FAVORITE}

plugins:
# https://github.com/neverendingqs/serverless-dotenv-plugin/pull/183#issue-1103321592
  - serverless-dotenv-plugin
  - serverless-offline

So here is what we can do/recommend users:

  • to use ${env:xxx} with .env, use the native Serverless Framework feature
  • to import all .env variables into functions, use this plugin

参考:

$ sls deploy
DOTENV: Loading environment variables from .env:
	 - REGION
	 - FAVORITE

Deploying src to stage dev (<REGION>)

✔ Service deployed to stack src-dev (217s)

functions:
  echo: echo (33 MB)
$ sls invoke local -f echo --data "hello"
DOTENV: Loading environment variables from .env:
	 - REGION
	 - FAVORITE
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Successfully loading your environment variables as follows;\\n my favorite is m-flo\",\n  \"input\": \"hello\"\n}"
}

4-2.PRやissueで紹介されていないけど動作確認が出来たserlverless.ymlの書き方

  • こちらは2系と3系両方で動作確認がとれた
    • ただし、環境変数の定義ファイルがdotenvではダメとややトリッキーな方法
service: src

# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
frameworkVersion: '3'
#frameworkVersion: '2'

custom:
  #dotenv:
  #  basePath: ./
  #REGION: ${env:REGION}
  REGION: ${file(./.env.json):REGION} ## <-- ココ
  nodejsVer: nodejs12.x
  #nodejsVer: nodejs14.x
  memorySize: 256
  timeout: 900
  TZ: Asia/Tokyo
  #FAVORITE: ${env:FAVORITE}
  FAVORITE: ${file(./.env.json):FAVORITE} ## <-- ココ

provider:
  name: aws

略

plugins:
  - serverless-dotenv-plugin
  - serverless-offline

参考:Serverless Variables

おまけ)Serverless Framework 2系で環境変数を扱うserverless.ymlの書き方

service: src

frameworkVersion: '2'

custom:
  #dotenv:
  #  basePath: ./
  REGION: ${env:REGION}
  nodejsVer: nodejs12.x
  memorySize: 256
  timeout: 900
  TZ: Asia/Tokyo
  FAVORITE: ${env:FAVORITE}

provider:
  name: aws

略

plugins:
  - serverless-dotenv-plugin
  - serverless-offline

参考:Serverless Framework: Plugins