AWS Lambda Web Adapter

React Router v7のチュートリアルを試す で作成したサンプルをAWS Lambda Web Adapter を使ってAWSのLambda上で動かす。

AWS Lambda Web AdapterのGitHubをみるとRemix example があるので参考にして進める。

設定

devcontainer.json

【開発環境】VSC+Dev Containers+AWS SAM+Lambda を参考に13-17行目、20-22行目を追加する

.devcontainer/devcontainer.json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
  "name": "React Router v7",
  // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
  "image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bullseye",
  "runArgs": ["--name", "react_router_v7-address-book"],
  // Features to add to the dev container. More info: https://containers.dev/features.
  "features": {
    "node": {
      "version": "v22.13.1"
    },
    "ghcr.io/devcontainers/features/docker-in-docker:2.12.0": {
      "enableNonRootDocker": "true",
      "moby": "true"
    },
    "ghcr.io/audacioustux/devcontainers/aws-sam-cli:1.0.1": {}
  },

  "mounts": [
    "source=${localEnv:HOME}${localEnv:USERPROFILE}/.aws/,target=/home/node/.aws/,type=bind,consistency=cached"
  ],

  // Use 'forwardPorts' to make a list of ports inside the container available locally.
  // "forwardPorts": [],
  // Use 'postCreateCommand' to run commands after the container is created.
  "postCreateCommand": "yarn install",
  // Configure tool-specific properties.
  "customizations": {
    // Configure properties specific to VS Code.
    "vscode": {
      "settings": {
        "eslint.nodePath": "./node_modules",
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "[typescript]": {
          "editor.defaultFormatter": "esbenp.prettier-vscode"
        },
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
          "source.fixAll.eslint": "explicit",
          "source.organizeImports": "explicit"
        },
        // github coplot setting
        "github.copilot.chat.completionContext.typescript.mode": "on",
        "github.copilot.chat.languageContext.typescript.enabled": true,
        // typescript setting
        "typescript.inlayHints.enumMemberValues.enabled": true,
        "typescript.inlayHints.functionLikeReturnTypes.enabled": true,
        "typescript.inlayHints.parameterNames.enabled": "all",
        "typescript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": true,
        "typescript.inlayHints.parameterTypes.enabled": true,
        "typescript.inlayHints.propertyDeclarationTypes.enabled": true,
        "typescript.inlayHints.variableTypes.enabled": true,
        "typescript.inlayHints.variableTypes.suppressWhenExpressionIsLiteral": true,
        "typescript.inlayHints.enabled": true,
        "cSpell.files": ["!package.json"]
      },
      // Add the IDs of extensions you want installed when the container is created.
      "extensions": [
        "dbaeumer.vscode-eslint",
        // 共通
        "esbenp.prettier-vscode",
        "mhutchie.git-graph",
        "eamodio.gitlens",
        "usernamehw.errorlens",
        "oderwat.indent-rainbow",
        "aaron-bond.better-comments",
        "streetsidesoftware.code-spell-checker"
      ]
    }
  }
  // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
  // "remoteUser": "root"
}

Dockerfile

yarnを使っているので、11-13行目のyarn関連のCOPYを追加する

Dockerfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
FROM public.ecr.aws/docker/library/node:22.13.1-bookworm-slim as builder
WORKDIR "/var/task"
ADD . .
RUN yarn set version 4.6.0 && yarn install && yarn build

FROM public.ecr.aws/docker/library/node:22.13.1-bookworm-slim
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter
WORKDIR "/var/task"
COPY --from=builder  /var/task/build /var/task/build
COPY --from=builder  /var/task/node_modules /var/task/node_modules
COPY --from=builder  /var/task/yarn.lock /var/task/yarn.lock
COPY --from=builder  /var/task/.yarn /var/task/.yarn
COPY --from=builder  /var/task/.yarnrc.yml /var/task/.yarnrc.yml
COPY --from=builder  /var/task/package.json /var/task/package.json
ENV NODE_ENV=production PORT=3000
CMD ["yarn", "start"]

template.yaml(AWS SAM)

Architecturesでarm64を指定する(必須ではない)

template.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  Remix Demo

  Sample SAM Template for Remix Demo

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 29

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      PackageType: Image
      MemorySize: 1024
      Architectures:
        - arm64
      Environment:
        Variables:
          RUST_LOG: info
      Events:
        Root:
          Type: HttpApi
    Metadata:
      DockerTag: v1
      DockerContext: .
      Dockerfile: Dockerfile

Outputs:
  FunctionApi:
    Description: "API Gateway endpoint URL for Prod stage for Express function"
    Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/"

デプロイ

デプロイはREADMEのDeploy to Lambda どおり進めれば問題なく進みます

デプロイ終了時に表示されるURLをブラウザで開けばチュートリアルと同じものが表示されます

参考