dayjournal memo

Total 975 articles!!

Try #015 – ZappaでDBもパッケージしたサーバーレスAPIを構築してみた

Yasunori Kirimoto's avatar


画像



画像



画像



画像





画像



この記事は、「Serverless Advent Calendar 2018」の2日目の記事です。



Zappaを利用して、できるだけシンプルにかつDBもパッケージしたサーバーレスAPIを構築してみました!


Zappaとは、AWSのLambdaやAPI Gateway等のサービスを利用して、アプリを構築するPythonのサーバーレスフレームワークです。Zappaを利用することにより、各サービスの細かい設定をしなくても手軽にサーバーレスアプリをデプロイできます。



今回は、サンプルで住所検索APIをサーバーレスアプリとして構築してみました。



Zappaでサーバーレスアプリを構築するために

① ローカル環境構築
② アプリ機能構築
③ AWSにデプロイ

の順番で進めていきます。




① ローカル環境構築



ローカル環境を構築する前に、pyenvとvirtualenvとAWS CLIの設定を事前にしておく必要があります。


この辺の記事を参考に進めると準備可能です。



事前準備が完了したら、実際にローカル環境を構築していきます。まずは、仮想環境を構築します。


仮想環境作成

pyenv virtualenv 3.6.0 sample181202


仮想環境切り替え

pyenv local sample181202


次に、今回構築するアプリに必要なパッケージとZappaを仮想環境にインストールします。


Flaskインストール

pip install Flask


peeweeインストール

pip install peewee


Zappaインストール

pip install zappa



② アプリ機能構築


アプリ構築用に準備するファイル一覧

db.sqlite: 住所検索用のSQLiteファイル
app.py: Flask、peewee等を盛り込んだPythonファイル
zappa_settings.json: Zappaの設定ファイル



今回は、DBもパッケージしたサーバーレスアプリを構築するためDBはSQLiteを利用します。

SQLiteの中には、国土地理院の電子国土基本図(地名情報)「住居表示住所」データを取り込み利用します。サンプルでは、札幌市のデータを取り込みました。

電子国土基本図(地名情報)「住居表示住所」データを利用するためには、国土地理院へ利用申請が必要です。


db.sqlite

画像



次に、APIを構築してみます。


app.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

#モジュールインポート
from flask import Flask, jsonify, abort, make_response, request
from peewee import *

#SQLite読み込み
database = SqliteDatabase("db.sqlite")

#ベースModel作成
class BaseModel(Model):
    class Meta:
        database = database

#addressテーブルのModel作成
class address(BaseModel):
    id = TextField()
    code = TextField()
    prefectures = TextField()
    city = TextField()
    ward = TextField()
    address = TextField()
    number01 = TextField()
    number02 = TextField()
    url01 = TextField()
    url02 = TextField()
    lon = TextField()
    lat = TextField()
    level = TextField()
    address_all = TextField()

#flaskのインスタンス作成
app = Flask(__name__)

#日本語表示対応
app.config['JSON_AS_ASCII'] = False

#JSON取得処理
@app.route('/', methods=['GET'])
def get_m():
    #URLのKeyとDBのKeyを比較
    try:
        #クエリパラメータを取得
        m_address = request.args.get('address_all')
        if m_address is not None:
            #like演算子追加
            m_address_all =  str("*" + m_address +"*")
            #検索結果を取得
            query = address.select().where(address.address_all % m_address_all)
            #変数初期化
            result = {}
            count = 0
            #検索結果でJSON作成
            for m in query:
                count = count + 1
                result[str(count)] = {
                    "data":{
                        "lon":m.lon,
                        "lat":m.lat,
                        "level":m.level,
                        "address_all":m.address_all
                        },
                    "result":True
                    }
                #結果は100件まで
                if count == 100:
                    break
            #最後にカウントをJSONに追加
            result["count"] = count
        else:
            #エラーJSON作成
            result = {
                "error": "クエリ文字列を設定してください。",
                "result":False
                }
        #JSONを出力
        return make_response(jsonify(result))
    except address.DoesNotExist:
        abort(404)

#エラー処理
@app.errorhandler(404)
def not_found(error):
    #エラーJSON作成
    result = {
        "error": "存在しません。",
        "result":False
        }
    #エラーJSONを出力
    return make_response(jsonify(result), 404)

#app実行
if __name__ == '__main__':
    app.run()


ローカル環境でアプリを確認してみます。


ローカルサーバー起動

python app.py

画像



クエリパラメータで検索したい住所を指定します。
http://127.0.0.1:5000/?address_all=北海道札幌市中央区

画像



ローカル環境で問題なければ、Zappaの設定ファイルを作成します。


設定ファイル作成

zappa init


作成された設定ファイルを適宜修正します。

zappa_settings.json


{
    "api": {
        "app_function": "app.app",
        "aws_region": "ap-northeast-1",
        "project_name": "zappa_sample",
        "runtime": "python3.6",
        "s3_bucket": "zappa-iqubzbin5"
    }
}



③ AWSにデプロイ


最後にZappaでアプリをデプロイします。



デプロイ

zappa deploy


デプロイ以外にもコマンドがあります。


削除

zappa undeploy

アップデート

zappa update

ログ確認

zappa tail


AWSのコンソールで確認してみます。


Lambda

画像



API Gateway

画像



公開されたAPIで動作確認してみます。
https://xxxxxxx.amazonaws.com/api/?address_all=北海道札幌市中央区
※Zappaにアップするとパスにapiが追加されます。

画像




これでDBもパッケージしたサーバーレスAPIの公開ができますね!



今回のサンプルでは経緯度も取得できるので、LeafletMapbox GL JS等のマップライブラリと組み合わせると、地図上に結果を可視化するアプリを構築することも可能になります!




※「このアプリケーションの作成に当たっては、国土地理院長の承認を得て、同院発行の電子国土基本図(地名情報)住居表示住所を使用した。(承認番号 平30情使、第928号)」



book

Q&A