【serverless-framework】1から始めるexpressをAWS Lambdaにデプロイ

# はじめに
メモ用。調査からの急ぎで書いたモノなので間違っていればご指摘ください。
やるとこはタイトルの通り。今回、セキュリティ等は考慮していないのであくまで「形にしたい」という人だけおすすめです。
AWSアカウントの作成、`node`のインストールだけは事前にやっておいてください。

* `AWS`
    * IAMでのユーザの作成と許可ポリシーの作成
    * アクセスキーの作成
    * CLIインストールとconfigure
* `serverless-http`
    * プロジェクトの作成
    * ローカルホストで起動
    * デプロイ

# 環境
* MacOS - AppleM1チップ - 16GBメモリ - Sonoma14.5
* `npx version` - `10.8.3`
* `node version` - `v22.5.1`
* `serverless ϟ framework` - `4.4.3`

https://www.serverless.com/

# `AWS`
## IAMでのユーザの作成と許可ポリシーの作成

* IAMにアクセスします。リージョンを設定することを忘れないで

https://us-east-1.console.aws.amazon.com/iam/home?region=ap-northeast-1#/home

<br>

* 左のタブの「ユーザー」から「ユーザーの作成」を押して
![SS 2024-10-01 23.54.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/1a6384d2-5c30-7389-e5d6-b1eedb070d9a.png)
<br>

* 任意のユーザ名を設定してください。アルファベット推奨
![SS 2024-10-02 0.00.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/b284d6d3-00f2-b032-1b44-58161145993d.png)
<br>

* 「ポリシーを直接アタッチする」から「ポリシーの作成」を押して
![SS 2024-10-02 0.00.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/e96c550d-08ad-771d-072a-2a69cdca50bd.png)
<br>

* 「JSON」を選択するとコードエディタが出てきます
![SS 2024-10-02 0.01.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/9d81efa3-987b-0bcd-740e-dfc69bf84155.png)


以下のように変更してください
```json:ポリシーエディタ
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Statement1",
			"Effect": "Allow",
			"Action": [
				"lambda:*",
				"iam:*",
				"s3:*",
				"cloudformation:*",
				"ssm:*",
				"apigateway:*",
				"logs:*"
			],
			"Resource": [
				"arn:aws:lambda:*:*:function:*",
				"arn:aws:iam::*:role/*",
				"arn:aws:s3:::*",
				"*",
				"*",
				"*",
				"*"
			]
		}
	]
}
```
<br>

* 任意のポリシー名と説明を記入してください。他特にいじる必要はありません
![SS 2024-10-02 0.19.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/244974d7-7789-3fff-1e10-6336ca0dc75f.png)
<br>

* 先ほどの画面に戻り、絞り込みタイプを「カスタマー管理」にすると、
![SS 2024-10-02 0.20.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/c2212a27-4a60-2d3a-cf44-5aa354fb09ce.png)
<br>

* 作成したポリシーが出てるので選択してあげます。ここも他でいじる必要は特にありません
![SS 2024-10-02 0.21.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/d87edfff-52a9-01e8-d525-c1adbd3faf16.png)
<br>

* 最終確認。「ユーザーの作成」を押してください。
![SS 2024-10-02 0.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/b7dd3733-8dd7-be2d-3356-e95a2d1f8a2e.png)
<br>

* 作成できました🎉
![SS 2024-10-02 0.24.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/168e24f9-be09-f6c8-0e44-13b82828d05c.png)

## アクセスキーの作成
* ユーザーの画面から「アクセスキーを作成」します
![SS 2024-10-02 0.24.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/232fa02d-679f-a4f3-1e92-2a256257525a.png)
<br>

* 「コマンドラインインターフェイス(CLI)」を選択して次へ
![SS 2024-10-02 0.28.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/83179dca-33ed-d755-b895-e08e1db6c61c.png)
<br>

* 任意の説明タグを入れてやります
![SS 2024-10-02 0.31.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/fc3bc834-7e57-056d-c3fa-06cd2099bb57.png)
<br>

* アクセスキーが生成されます。あとで使うので控えておきましょう。不安な人は、下の方にいくと`.csv`をダウンロードできるので保存しておきましょう。
![SS 2024-10-02 0.32.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/b670ec9c-4799-150a-05ed-954297254160.png)


## CLIインストールとconfigure
`brew`が一番手っ取り早いです。（他の方法でもできますが...）
これを機にmacOS勢の方はいれてみてはいかがでしょうか。

```terminal:terminal
$ brew install awscli
$ aws --version
aws-cli/2.17.27 Python/3.11.9 Darwin/23.6.0 source/arm64
```

https://brew.sh/ja/

先ほど控えたアクセスキーを使ってユーザと紐づけます。
```terminal:terminal
$ aws configure
AWS Access Key ID: [アクセスキーを入力]
AWS Secret Access Key: [シークレットアクセスキーを入力]
Default region name: [regionを入力]
Default output format: None  ※特に設定せずEnter
```

確認
```terminal:terminal
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ******************** shared-credentials-file    
secret_key     ******************** shared-credentials-file    
    region           ap-northeast-1      config-file    ~/.aws/config
```

参考：

https://zenn.dev/akakuro/articles/30f570b8863bef


# `serverless-http`
## プロジェクトの作成

* プロジェクトを作成したい場所まで移動し、以下のコマンドを実行。
* 今回は`AWS / Node.js / Express API`でやっていきます。
```terminal:terminal
$ npx serverless
Serverless ϟ Framework

Welcome to Serverless Framework V.4

Create a new project by selecting a Template to generate scaffolding for a specific use-case.

? Select A Template: … 
❯ AWS / Node.js / HTTP API
  AWS / Node.js / Express API
  AWS / Node.js / Express API with DynamoDB
  AWS / Node.js / Scheduled Task
  AWS / Node.js / Simple Function
  AWS / Python / HTTP API
  AWS / Python / Flask API
  AWS / Python / Flask API with DynamoDB
  AWS / Python / Scheduled Task
  AWS / Python / Simple Function
  AWS / Compose / Serverless + Cloudformation + SAM
```

* プロジェクト名を入力してやります。
```terminal:terminal
Create a new project by selecting a Template to generate scaffolding for a specific use-case.

✔ Select A Template: · AWS / Node.js / Express API

? Name Your Project: › serverless-express 
```
<br>

* プロジェクトの作成が完了します。初回だとログインを求められます。一番上の`Login / Register`を選択し、ブラウザが開くのでテキトーに登録しておきましょう。嫌な場合は`Ctr+C`しましょう。
![SS 2024-10-02 0.51.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/88d9228c-2723-54be-6643-e33be44e1f15.png)
<br>



* その後もプロジェクトを作成するたびに以下のようなものが出ます。作成しておくとダッシュボードなどでアクセス状況などを管理できますが、任意で大丈夫です。
```terminal:terminal
? Create Or Select An Existing App: … 
  Create A New App
  ...other pj
❯ Skip Adding An App
```
![SS 2024-10-02 0.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/c3bc7295-43b3-f9f1-97e6-08c5e9a01474.png)

## ローカルホストで起動

* `node_modules`をインストール
```terminal:terminal
$ npm install
```


* `handler.js`の下の方に以下を追記
```diff_javascript:handler.js
// ...

+ app.listen(3000, () => {
+     console.log("Server is running on port http://localhost:3000/");
+ });

exports.handler = serverless(app);
```

* `node`で起動。ホットリロードには対応していないので、更新のたびに再起動してやる必要があります。`nodeamon`を使うとホットリロードが可能になるのでデバッグしやすいです。

```terminal:terminal
$ node handler.js
Server is running on port http://localhost:3000/
```

https://qiita.com/moody_engineer/items/9bb3bb86a9d2053aeea7

* ポート3000にアクセスでちゃんと返ってきますね
![SS 2024-10-02 1.08.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/16bc5525-c3f3-0c85-3596-7dd2db92b8b2.png)

## デプロイ

* `serverless.yml`に以下を追記。`region`はcliで設定したものと同じものを推奨します。
* `package`は`functions`の中ではなく外なので注意
```diff_yaml:serverless.yml
# "org" ensures this Service is used with the correct Serverless Framework Access Key.
org: pam5596
# "service" is the name of this project. This will also be added to your AWS resource names.
service: serverless-express

provider:
  name: aws
  runtime: nodejs20.x
+ region: ap-northeast-1

functions:
  api:
    handler: handler.handler
    events:
      - httpApi: "*"

+ package:
+  include:
+    - node_modules/**
+    - handler.js
```
<br>

* 以下のコマンドでデプロイがされます
```terminal:terminal
$ npx serverless deploy

Deploying "serverless-express" to stage "dev" (ap-northeast-1)

✔ Service deployed to stack serverless-express-dev (44s)

endpoint: ANY - https://*********.execute-api.ap-northeast-1.amazonaws.com
functions:
  api: serverless-express-dev-api (922 kB)
```
<br>

* Aws Lambdaを確認してみましょう。ちゃんと作られています。GateWayも付随してます。
![SS 2024-10-02 1.16.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/663f420d-846c-2564-cad4-cfbd42e9f2ef.png)
<br>

* APIエンドポイント以降のパスはexpressで設定したルートと同じです。 
![SS 2024-10-02 1.18.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/f04fb8f8-3860-e2d1-6254-70b1e69400ff.png)

 # おまけ
 プロジェクトをきれいさっぱり消したい場合、消えてくれます
 
 ```terminal:terminal
$ npx serverless remove
Removing "serverless-express" from stage "dev" (ap-northeast-1)

✔ Service serverless-express has been successfully removed (21s)
 ```