Serverless FrameworkでSlackアプリを作ってみる
はじめに
こんにちは。永和システムマネジメント FDPメンバの坂部です。
FDPでは、4月からSlackアプリの作成に取り組んでいます。
今回は、下記のツールセットでSlackアプリを作ってみます。
- Bolt
- Python
- AWS Lambda
- コンテナイメージ
- AWS Lambda Function URLs
- Serverless Framework
- VS Code Remote Container
目指すのは、「hello」と発言すると、応答してくれるアプリです。
(Boltのチュートリアルにあるやつです)
VS Code Remote Containerの設定
開発環境にはVS Code Remote Containerを使用します。
./devcontainer/devcontainer.json
{ "name": "sample-serverless-slack-app", "dockerFile": "Dockerfile", // Lambdaコンテナイメージのデプロイで使うDocker "features": { "docker-in-docker": { "version": "latest", "moby": true, "dockerDashComposeVersion": "v1" } }, // AWSのクレデンシャルはコンテナ外の環境変数に設定して、コンテナ内に渡す "containerEnv": { "AWS_ACCESS_KEY_ID": "${localEnv:AWS_ACCESS_KEY_ID}", "AWS_SECRET_ACCESS_KEY": "${localEnv:AWS_SECRET_ACCESS_KEY}" }, "postCreateCommand": "pip install -r requirements.txt", "settings": { ... }, "extensions": [ ... ] }
./devcontainer/Dockerfile
# Python3.10を試したかったが、Lambdaのコンテナイメージが3.9までしかサポートしていない FROM python:3.9.11 # serverlessをインストール RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - RUN apt-get install -y nodejs RUN npm install -g serverless@3.12.0
Serverless Frameworkの設定
serverless.yml
service: sample-serverless-slack-app frameworkVersion: "3" provider: name: aws region: ap-northeast-1 ecr: images: appimage: path: ./ # 同じディレクトリのDockerfileを参照 iamRoleStatements: - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: - "*" # よくない 😡 functions: app: image: name: appimage url: true # AWS Lambda Function URLsを使う events: - http: method: post path: /slack/events
Lambdaの設定
Dockerfile
FROM public.ecr.aws/lambda/python:3.9 COPY requirements.txt ./ RUN pip install -r requirements.txt COPY app.py ./ CMD [ "app.handler" ]
requirements.txt
slack-bolt==1.13.0 boto3==1.12.42
app.py
import json import logging import os import boto3 from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler logging.basicConfig(level=logging.DEBUG) # SlackのクレデンシャルはSecrets Managerに格納している # serverlessに環境変数として渡した方が良いかも 🤔 secretsmanager = boto3.client("secretsmanager", region_name=<your_region>) secret_value = secretsmanager.get_secret_value(SecretId=<your_secret_id>) secret = json.loads(secret_value["SecretString"]) os.environ["SLACK_BOT_TOKEN"] = secret["SLACK_BOT_TOKEN"] os.environ["SLACK_SIGNING_SECRET"] = secret["SLACK_SIGNING_SECRET"] app = App(process_before_response=True) # 「hello」のメッセージに応答する @app.message("hello") def message_hello(message, say): say(f"Hey there <@{message['user']}>!") def handler(event, context): slack_handler = SlackRequestHandler(app=app) return slack_handler.handle(event, context)
デプロイしてみる
コンテナ外でAWSのクレデンシャルを設定します。
export AWS_ACCESS_KEY_ID=<your access key> export AWS_SECRET_ACCESS_KEY=<your secret access key>
あと、AWSコンソールでぽちぽちして、Secrets ManagerにSlackのクレデンシャルを登録しておきます。
デプロイします。
sls deploy
sls deploy Deploying sample-serverless-slack-app to stage dev (ap-northeast-1) Warning: Docker authentication token will be stored unencrypted in docker config. Configure Docker credential helper to remove this warning. ✔ Service deployed to stack sample-serverless-slack-app-dev (182s) endpoints: POST - https://??????.execute-api.ap-northeast-1.amazonaws.com/dev/slack/events app: https://???????????????.lambda-url.ap-northeast-1.on.aws/ functions: app: sample-serverless-slack-app-dev-app 1 deprecation found: run 'serverless doctor' for more details
下記を参考に、Slackアプリを作成します。
https://slack.dev/bolt-python/ja-jp/tutorial/getting-started-http#httpを利用したイベントを設定する あたりを参考に、発行されたURLをSlackアプリに設定します。
「hello」と発言してみます。
無事、動作しました 🎉
余談
2022/04/16時点で、Serverless Frameworkでよく使われるプラグインの、serverless-offlineがLambdaのコンテナイメージに未対応なので、注意したほうが良いかもです。