← ハンズオン一覧に戻る

AWS Hands-on / Serverless

受け取ったデータをデータベースに保存する

Lambda 関数から、サーバーレスのデータベース「DynamoDB」にデータを書き込みます。受け取った内容を貯めておき、あとから見返せる——アプリの「保存」のいちばん基本を、サーバーを立てずに体験します。コードは 1 行ずつ言葉で説明します。

● Lv.3 複数のサービスを組み合わせられる人 ⏱ 所要 40〜60 分 すべてコンソールで完結
01 — Prerequisites

はじめる前に

  • 必須AWS アカウントを持ち、マネジメントコンソールにサインインできること
  • 必須Lambda 関数をコンソールで作り、テストイベントで実行した経験があること
  • あると良い「データベース(データをためておく場所)」「表(テーブル)」のイメージ
  • あると良いLambda の権限(実行ロール)に、操作したいサービスの許可を足す、という考え方

※ このハンズオンは すべてコンソールだけで完結します。保存できたかどうかは、DynamoDB の画面で表(テーブル)を開いて確認します。

🌱 プログラミングがはじめての人へ

コードはこのページにすべて用意してあります。コピーして貼り付けるだけで動きます。書いてある内容は 1 行ずつ日本語で説明するので、いま意味が分からなくても大丈夫。「プログラムでデータを保存する」体験が目的です。

02 — References

参照する公式ドキュメント

手順に迷ったときや、用語の意味を確かめたいときに開きましょう。

※ リンク切れの場合は、ページタイトルで検索してください。

03 — Background

背景・シナリオ

プログラムは、動いている間はデータを覚えていますが、終わると忘れてしまいます。「受け取った内容をあとで見返したい」「貯めておきたい」となると、どこかに保存しておく場所が必要です。それがデータベースです。

AWS の DynamoDB は、サーバーの用意や管理が要らないサーバーレスのデータベースです。テーブル(表)を作っておき、そこへ項目(1 件分のデータ)を書き込んだり読み出したりします。今回は、Lambda が受け取ったデータを DynamoDB のテーブルに保存し、保存された内容を画面で確かめます。これで「処理する Lambda」と「貯めておく DynamoDB」が組み合わさり、サーバーレスで小さなアプリの土台ができます。

DynamoDB の「テーブル」「項目」って何?

テーブルはデータをためる表、項目はその1 行ぶんのデータです。各項目には「id」などの目印(キー)を付けて区別します。今回は、id と message(メッセージ)を持つ項目を保存します。

Lambda が DynamoDB を操作するのに、特別な準備は要る?

はい。Lambda には「DynamoDB に書き込んでよい」という権限を持たせる必要があります。Lambda の実行ロールに、その許可を足します(手順の中で行います)。「やってよいことだけを許可する」という、AWS 共通の考え方です。

Goal

Lambda 関数から DynamoDB のテーブルへデータを書き込み、DynamoDB の画面で、保存された項目(id とメッセージ)が表示されることを確認する。テストを変えて実行すると、項目が増えることも確かめる。

04 — Architecture

つくる構成

Lambda に入力(id とメッセージ)を渡すと、Lambda がそれを DynamoDB のテーブルに書き込みます。書き込まれた項目は、テーブルにどんどん貯まっていきます。

入力(event)
id = 1
message = はじめての保存
Lambda 関数
受け取って書き込む
DynamoDB テーブル「messages」(貯まっていく)
idmessage
1はじめての保存
22 件目のメッセージ
Lambda が動くたびに、テーブルに項目(1 件分のデータ)が増えていきます。
保存された内容は、DynamoDB の画面でいつでも見返せます。
05 — Requirements

要件

以下の要件を満たし、保存された項目が DynamoDB の画面に現れることを確認してください。

No要件
1リージョンは「東京(ap-northeast-1)」を使用する。
2DynamoDB テーブルを 1 つ作成する。テーブル名は messagesパーティションキーid(文字列)。
3Lambda 関数を 1 つ作成する。ランタイムは Python(最新版でよい)。本文のサンプル(受け取った id とメッセージを保存する)に置き換えて保存(デプロイ)する。
4Lambda の実行ロールに DynamoDB を操作できる権限を追加する(学習用に、例:マネージドポリシー AmazonDynamoDBFullAccess)。
5テストイベントに {"id": "1", "message": "はじめての保存"} を設定してテスト実行する。
6DynamoDB のテーブルの項目を表示し、保存された項目が現れていることを確認する(id を変えて再実行すると項目が増える)。
06 — Steps

構築の進め方

「テーブルを作る → 保存するコードを貼る → 権限を足す → 実行して画面で確認」の順に進みます。コードは貼り付けるだけ。意味は 1 行ずつ説明します。

  1. リージョンを合わせ、DynamoDB テーブルを作る

    リージョンが東京であることを確認し、DynamoDB コンソールで「テーブルの作成」を押します。テーブル名messagesパーティションキーid(タイプは文字列)を指定し、ほかは初期設定のまま作成します。

    テーブルを作成 — テーブルのキャパシティ設定(イメージ)

    読み込み/書き込みキャパシティモード

    オンデマンド
    使った分だけ課金。容量の事前設定が不要
    プロビジョンド
    読み込み・書き込みの容量を自分で確保

    学習用の少量アクセスなので「オンデマンド」を選びます

    パーティションキーとは

    各項目を区別するための主な目印(キー)です。今回は id をキーにするので、項目ごとに違う id を付けます。コードでもこの id という名前を使うので、つづりをそろえておきましょう。

  2. 保存するコードを貼り付ける

    Lambda コンソールで「関数の作成」→「一から作成」を選び、関数名 save-message、ランタイム Python(最新版)で作成します。「コードソース」の中身をすべて消して、次のコードを貼り付け、「Deploy」で保存します。

    ざっくり言うと:受け取った id とメッセージを、DynamoDB の表(テーブル)に 1 件保存するプログラムです。(細かい意味は、コードの下で 1 行ずつ説明します)

    lambda_function.py(このまま貼り付け)
    import boto3
    
    table = boto3.resource("dynamodb").Table("messages")
    
    def lambda_handler(event, context):
        table.put_item(Item={
            "id": event["id"],
            "message": event["message"]
        })
        return "保存しました"
    • import boto3Python から AWS のサービス(今回は DynamoDB)を操作するための道具(ライブラリ)を読み込んでいます。Lambda には最初から入っています。
    • table = boto3.resource("dynamodb").Table("messages")messages という名前のテーブルを操作する準備をして、table という入れ物に入れています。以降は table を通じて読み書きします。
    • def lambda_handler(event, context):関数の「入口」です。event に、保存したいデータ(id とメッセージ)が渡されてきます。
    • table.put_item(Item={ "id": ..., "message": ... })テーブルに1 件のデータ(項目)を書き込む命令です。event から取り出した id とメッセージを、項目として保存しています。
    • return "保存しました"処理が終わったことを表すために「保存しました」を返しています。
    テーブル名・キー名をそろえる

    コードの "messages""id" は、手順 1 で作ったテーブル名・キー名と同じつづりでなければなりません。違うと保存に失敗します。

  3. Lambda に「DynamoDB を操作できる権限」を足す

    関数の画面で「設定」タブ →「アクセス権限」を開き、表示されている実行ロールのリンクをクリックします(IAM の画面が開きます)。そこで「許可を追加」→「ポリシーをアタッチ」を選び、AmazonDynamoDBFullAccess を検索してアタッチします。

    なぜ権限が要るの?

    Lambda は初期状態では、ログを書く程度の権限しか持っていません。DynamoDB に書き込むには、その許可を実行ロールに足す必要があります。今回は学習のため操作全般を許可しますが、本番では「このテーブルへの書き込みだけ」のように絞るのが安全です(最小権限)。

  4. テストイベントを用意して実行する

    関数の「テスト」を押し、テストイベントの内容を次に置き換えて保存し、もう一度「テスト」で実行します。「実行結果: 成功」と表示され、結果に「保存しました」が返れば、書き込みの呼び出しは成功です。

    テストイベント(入力する内容)
    {
      "id": "1",
      "message": "はじめての保存"
    }
    id を変えて何度か試す

    id を "2""3" …と変えて実行すると、別々の項目として増えていきます。同じ id で実行すると、その項目は上書きされる点も、あとで画面で確かめてみましょう。

  5. DynamoDB の画面で保存された項目を確認する

    DynamoDB コンソールで messages テーブルを開き、「テーブルアイテムの操作」→「項目を返す(スキャン)」などで項目一覧を表示します。保存した id とメッセージの項目が現れているはずです。id を変えて実行したぶん、項目が増えていることも確認しましょう。

    これで「保存」が完成

    サーバーを 1 台も立てずに、「受け取って → 保存する」ができました。ここに前段の受付(API)を足せば、外から送られたデータを保存するアプリにも発展できます。

07 — Pitfalls

つまずきポイント

初学者がよく引っかかる箇所を先回りでまとめました。答えそのものは載せていませんが、「どこを見直せばよいか」の手がかりとして使ってください。

Pitfall 01 — 実行すると「AccessDenied」や権限のエラーが出る

「保存しようとすると、権限がないと怒られる」

Lambda の実行ロールに DynamoDB の権限が足りていない可能性が高いです。①手順 3 で、実行ロールに DynamoDB のポリシー(AmazonDynamoDBFullAccess など)をアタッチしたか②アタッチ後に少し待ってから再実行したかを見直しましょう。権限の反映に少し時間がかかることがあります。

Pitfall 02 — 「テーブルが見つからない」「キーが合わない」エラー

「ResourceNotFound や ValidationException が出る」

名前やキーの食い違いが原因のことが多いです。①コードのテーブル名 "messages" が、作ったテーブル名と一致しているか②パーティションキーの名前 "id" が、テーブルのキー名と一致しているか③テスト実行と同じリージョンにテーブルがあるかを確認しましょう。つづりの違いや、別リージョンでの作成がよくある原因です。

08 — Checklist

完了チェック

要件の再確認ではなく、画面のどこを見れば達成を確認できるかをまとめました。DynamoDB・Lambda のコンソールを開いて、次を順に確かめましょう。

  • DynamoDB に messages テーブルがあり、パーティションキーが id になっている。
  • Lambda 関数 save-message があり、コードが Deploy 済みになっている。
  • その関数の実行ロールに、DynamoDB を操作できる権限が付いている。
  • テスト実行が 「成功」し、結果に「保存しました」が返る。
  • DynamoDB のテーブルに、保存した項目(id とメッセージ)が表示される(id を変えると項目が増える)。
09 — Think

考えてみよう

手を動かすことに加えて、次の問いに自分の言葉で答えられるようにしておくと、理解がより深まります。

  1. プログラムは終わるとデータを忘れてしまうのに、DynamoDB に保存すると残りました。「プログラムの中で覚えておく」のと「データベースに保存する」のは、どう違うのでしょうか。
    ヒント
    プログラムが覚えているのは、動いている間だけの一時的なものです。終われば消えます。データベースに保存すると、プログラムが終わっても・別の実行からでも、同じデータを読み出せます。「一時的」と「ずっと残る」の違い、という観点で考えてみましょう。
  2. 今回は学習のため、Lambda に「DynamoDB の操作全般」を許可しました。実際の運用では、これをどう絞るとより安全でしょうか。
    ヒント
    「すべての DynamoDB」ではなく「この messages テーブルだけ」「書き込みだけ(削除は不可)」のように絞れます。許可を狭くするほど、間違いや乗っ取りのときにできることも限られます。「必要な操作・必要なテーブルだけ」を許可する、という観点で考えてみましょう。
  3. 今回は「テスト」ボタンからデータを保存しました。外から送られてきたデータを保存するアプリにするには、この関数の前に何を足せばよさそうでしょうか。
    ヒント
    URL にアクセスされたら動く受付(API)を前に置けば、外から送られたデータを受け取って、この関数で DynamoDB に保存できます。「受付(API)+ 処理(Lambda)+ 保管(DynamoDB)」という組み合わせを思い浮かべてみましょう。
10 — Clean up

後片づけ

学習で作ったものを片づけます。DynamoDB のテーブルは、置いておくだけでも少額の料金がかかる場合があるため、使い終わったら削除しましょう。

  1. DynamoDB テーブルを削除する:DynamoDB コンソールで messages テーブルを選び、削除します(保存した項目も一緒に消えます)。
  2. Lambda 関数を削除する:「関数」一覧で save-message を選び、「アクション」→「削除」で消します。
  3. ログを削除する(任意):CloudWatch の「ロググループ」から、この関数のログを削除できます。
Caution — テーブルの削除は元に戻せない

消す前に、残したいデータがないか確認

テーブルを削除すると、中に保存した項目もすべて消え、元に戻せません。残したいデータがある場合は、消す前に内容を控えておきましょう。学習用のデータだけなら、そのまま削除して大丈夫です。

コストに関する注意: DynamoDB は、保存しているデータ量と読み書きの量に応じて課金されます(オンデマンドの場合、使った分だけ)。新規アカウントには無料利用枠があり、今回のように少数の項目を保存して試す程度なら、ごく少額か無料の範囲に収まることが多いです。Lambda も呼び出し回数・実行時間に応じた課金で、毎月かなりの回数までの無料枠があります。IAM ロール・ポリシーの利用に料金はかかりません。使い終えたら、上の「後片づけ」でテーブルと関数を削除しておきましょう(テーブルを置いたままにすると、わずかでも料金が続くことがあります)。最新の料金は AWS の公式料金ページで確認してください。