【AWS】基礎的なウェブアプリの構築チュートリアルやってみた


はじめに

基本的なウェブアプリケーションを構築するチュートリアルをやってみた。所要時間も35分ほどで初心者にもとっつきやすい内容だった。一部スクショが貼ってなかったり画面が異なる箇所があったので、備忘録として残したい。

完成系は以下の通り。
First NameとLast Nameを入力し、Call APIを押すと、「Hello from Lambda, First Name Last Name」が表示される。

手順

S3で静的ウェブサイトを作成

※全て東京リージョンで行う
S3>「バケットを作成する」を選択する。

「バケット名」を入力する。他のバケット名と被らないように、一意のものとする。「次へ」を選択する。

下記のようにアクセス許可設定を変えて、警告に対してチェックボックスをオンにする。「次へ」を選択する。

内容を確認して、「バケットを作成」を選択する。

新しいバケットを選択する。プロパティ>「Static website hosting」を選択する。

「このバケットを使用してウェブサイトをホストする」を選択する。
下記のように項目を入力する。
インデックスドキュメント 「index.html」
エラードキュメント 「error.html」
入力したら、「保存」ボタンを選択する。

ローカルでエディタを開き、新しいファイルを作成し、次のHTMLを貼り付ける。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
</head>

<body>
    Hello World
</body>
</html>

ファイルをindex.htmlとして保存。

2つ目のファイルを作成し、次のテキストファイルを貼り付ける。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Error Page</title>
</head>

<body>
    Error Page
</body>
</html>

2つ目のファイルをerror.htmlとして保存。

アップロードボタンを選択。

index.htmlerror.htmlのファイルを追加する。「次へ」の選択をする。

「このオブジェクトへのパブリック読み取りアクセスを付与する」を選択する。「アップロード」ボタンを選択する。

リストからindex.htmlを選択する。

オブジェクトURLをクリックする。

Hello Worldが表示されるか確認する。

Lambdaでサーバーレス関数を構築

Lambda>関数の作成を選択する。
下記項目を入力する。
関数名 「HelloWorldFunction」
ランタイム 「Python 3.8」
「関数の作成」を選択する。

作成されたら、関数コードを下記のコードに置き換える。上部の「保存」ボタンを選択する。

# import the JSON utility package since we will be working with a JSON object
import json
# define the handler function that the Lambda service will use an entry point
def lambda_handler(event, context):
# extract values from the event object we got from the Lambda service
    name = event['firstName'] +' '+ event['lastName']
# return a properly formatted JSON object
    return {
    'statusCode': 200,
    'body': json.dumps('Hello from Lambda, ' + name)
    }


上部の「テストイベントを選択」>「テストイベントの設定」を選択する。

下記項目を入力する。
イベント名 「HelloWorldTestEvent」
jsonオブジェクト

{
"firstName": "Ada",
"lastName": "Lovelace"
}

「作成」ボタンを押す。

「テスト」ボタンを選択する。


「実行結果: 成功」が表示される。

API Gatewayを使用してサーバーレス関数をデプロイ

「APIを作成」を選択する。

REST APIボックスで「構築」ボタンを選択する。

下記項目を選択。
プロトコルの選択 「REST」
新しいAPIの作成 「新しいAPI」
API名 「HelloWorldAPI」
エンドポイントタイプ 「エッジ最適化」
「APIの作成」ボタンを選択。

リソース>アクション>メソッドの作成を選択。

「POST」を選択し、チェックマークを選択。
下記項目を選択。
統合タイプ 「Lambda 関数」
Lambda関数 「HelloWorldFunction」と入力
「保存」を選択。アクセス許可を知らせるメッセージでは「OK」を選択。

アクション>CORSの有効化を選択。

「POST」にチェックを入れる。「CORSを有効にして既存のCORSヘッダーを置換」を選択する。

「はい、既存の値を置き換えます」を選択。

アクション>APIのデプロイを選択。

APIのデプロイで、下記項目を入力。
デプロイされるステージ 「新しいステージ」
ステージ名 「dev」
「デプロイ」を選択する。

「URLを呼び出す」の横にあるURLを、コピーして保存。(あとでURLが必要になります。)

リソース>POST>小さな青い稲妻のアイコンを選択。

リクエスト本文に下記を入力。

{
    "firstName":"Grace",
    "lastName":"Hopper"
}

「テスト」ボタンを選択。


statusCode 200が表示される。

DynamoDBテーブルを作成

DynamoDB>テーブルの作成を選択。


下記項目を入力
テーブル名 「HelloWorldDatabase」
プライマリキー 「ID」
作成ボタンを押す。

Amazonリソースネーム (ARN)をコピーする。(あとで必要になります。)

Lambda>HelloWorldFunctionを選択。

アクセス権限タブを選択。ロール名を選択すると、新しいブラウザが開く。

アクセス権限タブでインラインポリシーの追加を選択。

JSONタブで下記項目を入力。YOUR-TABLE-ARNで先ほどコピーしたリソースネーム(ARN)に置き換える。

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "VisualEditor0",
        "Effect": "Allow",
        "Action": [
            "dynamodb:PutItem",
            "dynamodb:DeleteItem",
            "dynamodb:GetItem",
            "dynamodb:Scan",
            "dynamodb:Query",
            "dynamodb:UpdateItem"
        ],
        "Resource": "YOUR-TABLE-ARN"
    }
    ]
}

入力できたら「ポリシーの確認」を選択する。

名前 「HelloWorldDynamoPolicy」と入力し、「ポリシーの作成」を選択。

HelloWorldFunctionの関数コードで下記内容を入力する。
入力できたら右上の「保存」ボタンを選択。

# import the json utility package since we will be working with a JSON object
import json
# import the AWS SDK (for Python the package name is boto3)
import boto3
# import two packages to help us with dates and date formatting
from time import gmtime, strftime

# create a DynamoDB object using the AWS SDK
dynamodb = boto3.resource('dynamodb')
# use the DynamoDB object to select our table
table = dynamodb.Table('HelloWorldDatabase')
# store the current time in a human readable format in a variable
now = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())

# define the handler function that the Lambda service will use as an entry point
def lambda_handler(event, context):
# extract values from the event object we got from the Lambda service and store in a variable
    name = event['firstName'] +' '+ event['lastName']
# write name and time to the DynamoDB table using the object we instantiated and save response in a variable
    response = table.put_item(
        Item={
            'ID': name,
            'LatestGreetingTime':now
            })
# return a properly formatted JSON object
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda, ' + name)
    }

テストボタンを選択。
実行結果: 成功が表示される。

DynamoDB>テーブルを選択。テーブルのHelloWorldDatabaseを選択する。

Ada Lovelaceが表示されている

REST APIを呼び出す

index.htmlファイルを下記のように書き換える。その際、YOUR-API-INVOKE-URLをAPI呼び出しURLに書き換える。そしてファイルを保存する。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
    <!-- Add some CSS to change client UI -->
    <style>
    body {
        background-color: #232F3E;
        }
    label, button {
        color: #FF9900;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 20px;
        margin-left: 40px;
        }
     input {
        color: #232F3E;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 20px;
        margin-left: 20px;
        }
    </style>
    <script>
        // define the callAPI function that takes a first name and last name as parameters
        var callAPI = (firstName,lastName)=>{
            // instantiate a headers object
            var myHeaders = new Headers();
            // add content type header to object
            myHeaders.append("Content-Type", "application/json");
            // using built in JSON utility package turn object to string and store in a variable
            var raw = JSON.stringify({"firstName":firstName,"lastName":lastName});
            // create a JSON object with parameters for API call and store in a variable
            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: raw,
                redirect: 'follow'
            };
            // make API call with parameters and use promises to get response
            fetch("YOUR-API-INVOKE-URL", requestOptions)
            .then(response => response.text())
            .then(result => alert(JSON.parse(result).body))
            .catch(error => console.log('error', error));
        }
    </script>
</head>
<body>
    <form>
        <label>First Name :</label>
        <input type="text" id="fName">
        <label>Last Name :</label>
        <input type="text" id="lName">
        <!-- set button onClick method to call function we defined passing input values as parameters -->
        <button type="button" onclick="callAPI(document.getElementById('fName').value,document.getElementById('lName').value)">Call API</button>
    </form>
</body>
</html>

「アップロード」ボタンを選択。

index.htmlファイルを追加して、「次へ」ボタンを選択。
パブリックアクセス許可の管理で「このオブジェクトへのパブリック読み取りアクセスを付与する」を選択する。左下のアップロードボタンを選択する。

index.html>「オブジェクト URL」を選択する。

ウェブアプリがブラウザに読み込まれる。
名前 (または任意の名前) を入力し、「API を呼び出す」ボタンをクリック。
「Hello from Lambda, First Name Last Name」が表示される。

まとめ

サーバーレスでウェブアプリを構築する技術を学んだ。これらを応用し、今後ウェブアプリ等を作成したいと思う。