Serverless Framework で .env ファイルを使って Python で記述した Lambda 関数の環境変数を設定する方法
はじめに
アノテーション テクニカルサポートの川崎です。
社内育成の素材として、Serverless Framework を使用してデプロイするアプリを、アプリ作成の課題として、チームのメンバーに取り組んでもらっております。
その過程で経験したことを、Serverless Framework のデプロイ手順としてまとめてみます。
今回は、トークンやAPIキーを、最低限、コードのバージョン管理に含めずに利用する方法を確認しました。
git で管理するべきでない機密情報を取り扱う際に、よく利用される手段の1つとして .env があります。 Serverless Framework で .env ファイルを使い、環境変数を設定する手順について確認しました。
ご注意
このブログでは機密情報を .env ファイルに平文のまま記載する方法を説明しています。
AWS の SSM パラメータストアや Secrets Manager を利用し、暗号化することで、 トークンやAPIキーをよりセキュアに処理する手段が用意されていますので、必要に応じてご利用ください。
.env を利用する2つの方法
Serverless Framework には serverless-dotenv-plugin というプラグインがあります。 一方で、Serverless Framework の v3 では .env の利用はネイティブサポートされており、 プラグインを使わなくても .env を利用することができます。
以下では、プラグインを使わない方法を説明していきます。
- .env のネイティブサポートによる方法 ← このブログで説明する方法
- serverless-dotenv-plugin を使う方法
.env のネイティブサポート (serverless-dotenv-plugin を使わない方法)
serverless.yml で「useDotenv: true」を指定することで、 .env から環境変数を読み込む機能を有効化できます。
それでは、手順を見ていきます。
テンプレート「aws-python3」を指定して、Serverless サービスを新規作成します。
% mkdir dotenv1 % cd dotenv1 % sls create --template aws-python3 % rm handler.py % touch lambda_function.py
テンプレートから生成された handler.py は削除し、lambda_function.py というファイル名で、Lambda Python のサンプルコードを記述します。
今回は、Slack APIを用いて、指定のチャンネルからメッセージを取得する Python の Lambda 関数を作成します。
Slack API のアプリを作成する手順は、本ブログでは触れませんので、 下記ブログ記事などを参考にしていただければと思います。 (Slack API のアプリのスコープも設定する必要があります。)
Slack に関連する処理は、別ファイル slack_requests.py に切り出しています。
5-6行目で、Lambda 関数の環境変数から TOKEN と CHANNEL_ID の値を取得します。 TOKEN と CHANNEL_ID を指定して、Slack API の conversations.history にアクセスし、メッセージを取得します。
from slack_requests import get_messages_from_channel def lambda_handler(event, context): # チャンネルから最新のメッセージを取得する messages = get_messages_from_channel() latest_message = messages[0] if messages else None return None
import os import json import requests TOKEN = os.environ["SLACK_BOT_TOKEN"] CHANNEL_ID = os.environ["CHANNEL_ID"] def get_messages_from_channel(): url = "https://slack.com/api/conversations.history" headers = {"Authorization": f"Bearer {TOKEN}"} payload = {"channel": CHANNEL_ID} response = requests.get(url, headers=headers, params=payload) return response.json().get("messages")
テンプレートから生成された serverless.yml を以下の内容で上書きします。
4行目で「useDotenv: true」を指定して、.env から環境変数を読み込む機能を有効にしています。 デフォルトでは false です。
14-16行目で、Lambda 関数の環境変数を追加しています。
以上の設定を行うことで、.env ファイルに指定した内容を読み込んで、Lambda 関数の環境変数に指定することができます。便利ですね!
※ .env ファイルに指定する内容は、後述します。
service: dotenv1 frameworkVersion: '3' useDotenv: true provider: name: aws runtime: python3.11 region: ap-northeast-1 functions: slack-request: handler: lambda_function.lambda_handler environment: SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN} CHANNEL_ID: ${env:CHANNEL_ID} plugins: - serverless-python-requirements
serverless.yml の設定ができたら、serverless-python-requirements プラグインをインストールします。
Python を使う場合は、ほぼ必須のプラグインですね!
利用する外部モジュール名を、requirements.txt ファイルに記述しておきます。
% sls plugin install -n serverless-python-requirements % echo requests > requirements.txt
.env ファイルを作成し、SLACK_BOT_TOKEN、CHANNEL_ID の値を記述します。
% touch .env
SLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx CHANNEL_ID=Cxxxxxxxxxx
git 管理から除外するために、忘れずに .gitignore ファイルに「.env」を追記しておきます。
# Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # Serverless directories .serverless .env
上記の設定ができたら、デプロイを実行します。
% sls deploy --aws-profile sls-user
デプロイが成功したら、invoke コマンドで、デプロイした Lambda 関数を実行してみます。
% sls invoke -f slack-request --aws-profile sls-user Running "serverless" from node_modules { "bot_id": "XXXXXXXXXXX", "type": "message", "text": "Slack のテストメッセージ", "user": "XXXXXXXXXXX", "ts": "1698998672.511469", "app_id": "XXXXXXXXXXX", "blocks": [ { "type": "rich_text", "block_id": "xxxxx", "elements": [ { "type": "rich_text_section", "elements": [ { "type": "text", "text": "Slack のテストメッセージ" } ] } ] } ], "team": "XXXXXXXXXXX", "bot_profile": { "id": "XXXXXXXXXXX", "deleted": false, "name": "sample-channel1", "updated": 1692781566, "app_id": "XXXXXXXXXXX", "icons": { "image_36": "https://a.slack-edge.com/xxxxx/img/plugins/app/bot_36.png", "image_48": "https://a.slack-edge.com/xxxxx/img/plugins/app/bot_48.png", "image_72": "https://a.slack-edge.com/xxxxx/img/plugins/app/service_72.png" }, "team_id": "XXXXXXXXXXX" } }
Lambda 関数が実行され、指定のチャンネルから最新のメッセージを取得できました!
まとめ
Serverless Framework の v3 では .env の利用方法として、2つの方法があり、 本ブログではネイティブサポートによる方法を説明しました。
- .env のネイティブサポートによる方法
- serverless-dotenv-plugin を使う方法
最初は、どちらを使えばいいのかわからず、少々混乱したのですが、 手順としては、シンプルな方法で実現されているのが確認できました。
参考資料
[1] Resolution of environment variables
[2] Serverless Framework - Upgrading to v3
[3] Serverless Framework - AWS Lambda Guide - Serverless.yml Reference
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。