0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hono使ってLambdaにWebAPIを爆速公開

Last updated at Posted at 2025-03-25

はじめに

KG-7thの槙島です。

以前作成したTypeScriptベースのWebAPIをリメイクして手早く公開したいです。
調べてみてHonoフレームワークが一番適していると感じたため、試してみました。

Honoのセットアップ

たま~に聞くHonoフレームワーク。
どうやら爆速で開発できるみたいなのでやってみよう。

注意

デプロイでDockerが必要になるので、自分はVirtulBoxのUbuntuで実施してます。
aws configure ssoで認証情報を設定済みです。多分これしないとデプロイできないです。

AWS CDK CLIをインストール

Honoライブラリの手順の中で出てきた。便利そうなのでこの機会に入れてみる

# インストール
npm install -g aws-cdk
# CDKのAWS環境内のセットアップ
cdk bootstrap

lambda関数のテンプレを生成

cdk init app -l typescript

Honoのインストール

npm i hono

Lambda実行ファイルの作成

mkdir lambda

lambdaフォルダの中にindex.tsを作成

index.tsの中身

import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'

const app = new Hono()

app.get('/', (c) => c.text('Hello Hono!'))

export const handler = handle(app)

lib/ans-automate-stack.tsの中身

import * as path from 'path';
import * as cdk from 'aws-cdk-lib'
import { Construct } from 'constructs'
import * as lambda from 'aws-cdk-lib/aws-lambda'
import * as apigw from 'aws-cdk-lib/aws-apigateway'
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'

export class SnsAutomateStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props)

    // Lambda Layerの作成 (assets を指定)
    const layer = new lambda.LayerVersion(this, 'arn:aws:lambda:ap-northeast-1:123456789012:layer:SnsAutomateLayer:2', {
      code: lambda.Code.fromAsset(path.join(__dirname, '../assets')),
      compatibleRuntimes: [lambda.Runtime.NODEJS_20_X], // Node.jsランタイムを指定
      description: 'Lambda Layer for SNS Automate project',
    });

    const fn = new NodejsFunction(this, 'lambda', {
      functionName: "SnsAutomateFunction",
      entry: 'src/index.ts',
      handler: 'handler',
      runtime: lambda.Runtime.NODEJS_20_X,
      layers: [layer], // 作成したレイヤーを追加
      timeout: cdk.Duration.seconds(20), // 少し長め
      memorySize: 256, // 128だと動かなかった
      role: cdk.aws_iam.Role.fromRoleArn(this, 'SnsAutomateFunctionRole', 'arn:aws:iam::123456789012:role/SnsAutomateFunctionRole'),
      environment: {
        ROOT_URL: '/opt', // レイヤー内のアセットを参照するために設定
      },
    })
    fn.addFunctionUrl({
      authType: lambda.FunctionUrlAuthType.NONE,
    })
    new apigw.LambdaRestApi(this, 'myapi', {
      handler: fn,
    })

    // CloudWatch Eventsルールを作成
    new cdk.aws_events.Rule(this, 'SnsAutomateWeatherTweetScheduleRule', {
      ruleName: "SnsAutomateWeatherTweetScheduleRule",
      // 毎朝7時に実行
      schedule: cdk.aws_events.Schedule.cron({ minute: '0', hour: '22' }),
      targets: [new cdk.aws_events_targets.LambdaFunction(fn)],
    });
  }
}


Lambda Layerについて

画像やフォントなどの静的ファイルはそのままデプロイしてもついてきません。
Layerに入れることでLambda関数から扱うことができます。

今回はすでに作成済みのため、作成したLayerのARNを指定しています
(デプロイすることでLayerに静的ファイルがアップロードされるみたい)

const layer = new lambda.LayerVersion(this, 'arn:aws:lambda:ap-northeast-1:123456789012:layer:SnsAutomateLayer:2', {

なお、まだ作成していない場合は適当な名前を入れるとLayerが作成されます

    const layer = new lambda.LayerVersion(this, 'SnsAutomateLayer', {

関数にアタッチするロールについて

SnsAutomateFunctionRoleには以下のポリシーを許可しています。

image.png

SSMでパラメタを取得してきているのでSSMのread用のパーミッションを、
Cloudwatchのログを確認したいのでBasicExecute・・・を適用しています。

関数に紐づけているのは以下の箇所です。

role: cdk.aws_iam.Role.fromRoleArn(this, 'SnsAutomateFunctionRole', 'arn:aws:iam::123456789012:role/SnsAutomateFunctionRole'),

デプロイ

cdk deploy

デプロイ成功!

image.png

出てきたURLにアクセスして問題ないことを確認

image.png

結論

早い・・・
RemixのLambda-web-adapterで右往左往していた時の30倍は早いぞ・・・

今回のコードはこちら
これから使っていく予定なので、コミットのURLを載せておきます。。

感想

CDKを使ったので、裏側で何が起きてるのか正直よくわかってない。
これからドキュメント見直してみます。

ところで、これ別の端末からデプロイしたら別のLambda関数としてデプロイされてしまうのでは。。

追記

気になったところをperplexityに聞いてみた

質問①

この場合、環境変数はどこで管理すればよいでしょうか?

回答

CDKで環境変数を管理する主な方法は3通りあります:

  1. CDKスタック内での直接設定(非機密情報向け)
const fn = new NodejsFunction(this, 'lambda', {
  entry: 'lambda/index.ts',
  environment: {
    API_KEY: 'your_api_key',
    STAGE: 'production'
  }
});
  1. AWS Systems Manager Parameter Store(推奨)
import * as ssm from 'aws-cdk-lib/aws-ssm';

const fn = new NodejsFunction(this, 'lambda', {
  entry: 'lambda/index.ts',
  environment: {
    DB_PASSWORD: ssm.StringParameter.valueForStringParameter(this, '/config/DB_PASSWORD'),
  }
});
  1. AWS Secrets Manager(機密情報向け)
import * as secrets from 'aws-cdk-lib/aws-secretsmanager';

const secret = secrets.Secret.fromSecretNameV2(this, 'Secret', 'my-secret');

const fn = new NodejsFunction(this, 'lambda', {
  entry: 'lambda/index.ts',
  environment: {
    SECRET_VALUE: secret.secretValue.toString(),
  }
});

質問②

デプロイ時のLambdaの設定
(なんという名前の関数としてデプロイするのか、どのVPCに接続するのかなど)を行うにはどうすればよいですか?

回答

CDKスタックの設定例:

import * as ec2 from 'aws-cdk-lib/aws-ec2';

const fn = new NodejsFunction(this, 'lambda', {
  entry: 'lambda/index.ts',
  functionName: 'MyHonoFunction', // 関数名指定
  runtime: lambda.Runtime.NODEJS_20_X,
  memorySize: 512, // メモリサイズ
  timeout: cdk.Duration.seconds(10), // タイムアウト
  architecture: lambda.Architecture.ARM_64, // ARMアーキテクチャ
  
  // VPC設定
  vpc: ec2.Vpc.fromLookup(this, 'VPC', { vpcId: 'vpc-12345' }),
  vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
  securityGroups: [/* セキュリティグループ配列 */]
});

主要な設定項目:

  • プロパティ 説明 デフォルト値
  • functionName Lambda関数名 CDK自動生成
  • memorySize メモリ割当量(MB) 128
  • timeout 実行制限時間 3秒
  • architecture CPUアーキテクチャ X86_64
  • vpc 接続するVPC なし
  • securityGroups 適用するセキュリティグループ 自動生成
  • ベストプラクティス:
  • 関数名はfunctionNameで明示的に指定(CDKの自動生成名は可変)

VPC接続時はPrivate Subnet + NAT Gateway構成を推奨

開発環境と本番環境で設定を分ける場合:

const isProduction = process.env.STAGE === 'production';

new NodejsFunction(this, 'lambda', {
  memorySize: isProduction ? 1024 : 256,
  timeout: isProduction ? 30 : 10
});

補足
記事のサンプルコードを拡張する場合は、CDKスタックファイル(lib/*-stack.ts)のLambda関数定義部分を修正します。デプロイ時はcdk deployを再実行すれば、変更内容が自動反映されます。

とのこと。まだ試してないので参考程度に。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?