#本投稿の背景
フットサル大会の運用をシステム化( こちらの記事 )したのですが、
2020年3月からコロナの影響でフットサルの大会は実施されていません。。
この状況で以下を考えました。
・コロナで大会が中止。システム運用している仮想マシンは24時間 x 365日稼働する必要なし
・大会結果を参照したい人がいれば、そのタイミングで参照できればよい
・内容はチーム順位、得点者を表示するシンプルなものなので、Wordpressでなくてもよい
それを解決するのが、「サーバレス」と思ったので、
実験的にOCIでサーバレス「Oracle Functions」でWeb動的サイトを作ってみました。
※息子たちがF1マシンの絵をかいていたので、
それを使ったWebサイトを作ろうと思ったのも理由です。
#構成図
・DBは Autonomous Databaseを使用 ※無料枠の[Always free]
・Oracle Functionsでは(「チーム一覧ページ」、「チーム詳細ページ」)を作成
※いずれのページもDBに接続してデータからページ内容を作成しています
(静的ページ表示ではありません)
※詳細表示ページではオブジェクトストレージに格納した画像を参照しています
・API Gatewayでユーザから接続するエンドポイントをまとめる
#実際につくってみたWebサイト
#サーバレス(Oracle Functions)でWebサイトを構築する流れ
以下の手順で構築します
1.Autonomous Databaseを作成
2.画像ファイルをオブジェクトストレージに格納
3.ネットワークの作成
4.Oracle Functions を使う前の準備
5.Oracle Functions 「チーム一覧ページ」作成
6.API Gatewayの作成
7.Oracle Functions 「チーム詳細ページ」作成
8.「チーム一覧ページ」の「チーム詳細ページ」動作確認
※構築の事前準備として
コンパートメント「serverless」を作成しており、Oracle Functions等はコンパートメント「serverless」に作成します。
※設定手順などの詳細は、折りたたんでいるので、確認は ▶ をクリックください
#1.Autonomous Databaseを作成
Autonomous Databaseに2つのテーブルを作成します。
「チーム一覧ページ」、「チーム詳細ページ」で使用するテーブル・データとなります。
##1-1.Autonomous Databaseを作成
Autonomous Databaseを作成する詳細手順はこちら
[Oracle Database] - [Autonomous Database]を選択
「コンパートメント」を確認して、[Autonomous Databaseの作成]をクリック
「コンパートメント」、「表示名」、「データベース名」を設定。
「ワークロード・タイプ」は[データウェアハウス]、「デプロイメント・タイプ」は[共有インフラストラクチャ」を選択
##1-2.Autonomous Database の wallet を取得
Autonomous Database の wallet を取得する詳細手順はこちら
Autonomous Databaseには暗号化およびSSL相互認証を利用した接続が前提としており、そのため接続する際はクレデンシャル・ウォレット(Credential.zipファイル)を利用する必要があります
https://oracle-japan.github.io/ocitutorials/database/adb104-connect-using-wallet/
##1-3.DBスキーマ、テーブル作成
DBスキーマ、テーブル作成する詳細手順はこちら
[データベース・アクション]をクリック
[ユーザの作成]をクリック
ユーザ情報とWebアクセスを有効、表領域を割り当て、[ユーザの作成]をクリック
コンソール画面右上をみると、ADMINでログインになっているので、[サインアウト]をクリック
作成したユーザ名、パスワードを入力して[サインイン]をクリック
[ワークシート]にSQLを入力して、[実行(赤枠)]をクリックしてSQLを実行
CREATE TABLE TEAM
(
TEAM_ID NUMBER ,
TEAM_NAME VARCHAR2 (100) ,
IMG_URL VARCHAR2 (100) ,
CONSTRAINT PK_TEAM PRIMARY KEY(TEAM_ID)
) ;
CREATE TABLE F1DRIVER
(
TEAM_ID NUMBER ,
DRIVER_NO NUMBER ,
DRIVER_NAME VARCHAR2 (100),
CONSTRAINT PK_F1DRIVER PRIMARY KEY ( TEAM_ID, DRIVER_NO )
) ;
あとは、データを登録。
#2.画像ファイルをオブジェクトストレージに格納
「チーム詳細ページ」で表示する画像をオブジェクトストレージに格納します。
バケットを作成して、画像ファイルをアップロードして、可視性の設定をします。
##2-1.オブジェクト・ストレージの設定
オブジェクト・ストレージ設定する詳細手順はこちら
#3.ネットワークの作成
Oracle Functions、API Gatewayを配置するネットワークを作成します。
※VCNウィザードでネットワークを作成します
##3-1.VCNウィザードを実行
VCNウィザードを実行する詳細手順はこちら
##3-2.ネットワークセキュリティ設定
ネットワークセキュリティ設定する詳細手順はこちら
#4.Oracle Functions を使う前の準備
Oracle Functionsを使う前準備をします。
ここではCloud shellを使用してOracle Functionsをデプロイする設定とOracle Functionsを登録するアプリケーションの設定を行います。
事前準備の詳細は以下のページを参照ください(わかりやすく解説されています)
https://oracle-japan.github.io/ocitutorials/cloud-native/functions-for-beginners/
##4-1.Cloud shellを設定
Cloud shellを設定する詳細手順はこちら
ユーザ設定の認証トークンを取得します。
※Oracle Functions管理するOracle提供のプライベートDockerレジストリのログインに必要
コンソール画面の人のアイコンをクリックして、[ユーザ設定]をクリック
[認証トークン]-[トークンの生成]をクリック
[説明]を入れて、[トークンの生成]をクリック
「生成されたトークン」の[コピー]をクリック
※この情報を控えておきます。あとで必要になります。
コンソール画面の人のアイコンをクリックして、[テナンシ]をクリック
「テナンシ情報」のOCIDの[コピー]をクリック
※この情報を控えておきます。あとで必要になります。
Oracle FunctionsをデプロイするためのにOracle Functions CLIを利用して環境を作成します。
開発環境の設定は、fn updateコマンドを使用して行います。
>https://oracle-japan.github.io/ocitutorials/cloud-native/functions-for-beginners/
※cloud Shellで以下のコマンドを入力していきます。
リージョンを設定します。東京リージョンの場合はap-tokyo-1
fn use context ap-tokyo-1
テナンシーのOCIDを設定
fn update context oracle.compartment-id ocid1.tenancy.oc1..aaaaaaa<省略>
レジストリ名を登録します
※Oracle Functionsを管理するOracle提供のプライベートDockerレジストリ
fn update context registry iad.ocir.io/xxxxx/functions-serverless
fn update context registry iad.ocir.io/<オブジェクト・ストレージ・ネームスペース>/<任意の名前>
レジストリにログイン
パスワードは「トークンの生成」で作成したものを入力
docker login nrt.ocir.io
##4-2.アプリケーションの作成
アプリケーションを作成する詳細手順はこちら
#5.Oracle Functions 「チーム一覧ページ」作成
ここからは、Oracle Functions を作成します。
ここで実施する作業は、
作業ディレクトリにPythonのコード、Dockerイメージを作成するための
各種ファイルを準備します。結構あります。。
今回、Oracle functions、Dockerfileをさわってみてのイメージ(自分の理解)
##5-1.「チーム一覧ページ」functions [f1_teamlist]の作業ディレクトリを作成
「チーム一覧ページ」functions [f1_teamlist]作業ディレクトリを作成する詳細手順はこちら
##5-2.Oracle Instantclientのメディア、Autonomous Database walletを配置
Oracle Instantclientのメディア、Autonomous Database walletを配置する詳細手順はこちら
Oracle Instantclientの.zipを media フォルダにコピー、
walletファイルを dbwalletフォルダに解凍して格納
cd
mkdir f1_teamlist/media
cp instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip f1_teamlist/media
unzip Wallet_SERVERLESS.zip -d f1_teamlist/dbwallet
##5-3.Pythonのメイン処理「func.py」を作成
Pythonのメイン処理「func.py」を作成する詳細手順はこちら
import io
import os
from fdk import response
import cx_Oracle
def handler(ctx, data: io.BytesIO=None):
try:
#DB接続情報設定
username = "SCOTT"
password = "WElcome12345"
db_url = "serverless_medium"
#DB接続、データ取得
con = cx_Oracle.connect(username, password, db_url)
cur = con.cursor()
cur.execute('Select * from team')
rows = cur.fetchall()
strdata=""
for r in rows:
strdata = strdata + "<tr><td><a href='https://iba2rxxxxxx.apigateway.ap-tokyo-1.oci.customer-oci.com/f1detail/v1?teamid=" + str(r[0]) + "'>" + str(r[1]) + "</a></td></tr>"
#HTML作成
html = ""\
"<html lang='ja'>"\
"<head><title>F1 Team</title></head>"\
"<meta charset='utf-8'>"\
"<body>"\
"<font size='5'><b>F1チーム一覧</b> </font>"\
"<table border='1' style='border-collapse: collapse'>"\
" %s "\
"</table>"\
"</body>"\
"</html>"
resp = html % (strdata)
except Exception as e:
print('ERROR: Missing configuration keys, secret ocid and secret_type', e, flush=True)
return response.Response(
ctx,
response_data=resp,
headers={"Content-Type": "text/html"}
)
##5-4.requirements.txtに cx_Oracle を追加
requirements.txtに cx_Oracle を追加する詳細手順はこちら
requirements.txtに cx_Oracle を追加
fdk
cx_Oracle
##5-5.Dockerfile を新規追加
Dockerfile を新規追加する詳細手順はこちら
FROM oraclelinux:7-slim
WORKDIR /function
RUN groupadd --gid 1000 fn && adduser --uid 1000 --gid fn fn
RUN yum -y install python3 oracle-release-el7 && \
yum install -y unzip && \
yum install -y libaio-devel && \
rm -rf /var/cache/yum
ENV ORACLE_HOME=/function/instantclient_19_14
ENV LD_LIBRARY_PATH=/function/instantclient_19_14/lib:$LD_LIBRARY_PATH
ENV PATH=/function/instantclient_19_14:$PATH
ADD media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip /function/media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip
RUN unzip /function/media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip -d /function/tmp && \
mkdir /function/instantclient_19_14 && \
mv /function/tmp/instantclient_19_14 /function/instantclient_19_14/lib
COPY dbwallet/* /function/instantclient_19_14/network/admin/
RUN rm -f /function/media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip
ADD . /function/
RUN pip3 install --upgrade pip
RUN pip3 install --no-cache --no-cache-dir -r requirements.txt
RUN rm -fr /function/.pip_cache ~/.cache/pip requirements.txt func.yaml Dockerfile README.md
ENV PYTHONPATH=/python
ENTRYPOINT ["/usr/local/bin/fdk", "/function/func.py", "handler"]
##5-6.「チーム一覧ページ」Oracle Functions [f1_teamlist]をデプロイ
「チーム一覧ページ」Oracle Functions [f1_teamlist]をデプロイする詳細手順はこちら
#6.API Gatewayの作成
API Gatewayを使う事でUserからアクセスするエンドポイントを1つにまとめるメリットがあります。
(今回はOracle Functionsは2つしかありませんが、サイトのページが増える事を見越して設定します)
##6-1.API GatewayからOracle Functions[f1_teamlist]を実行できる設定を行う
API GatewayからOracle Functions[f1_teamlist]を実行できるよう設定する詳細手順はこちら
「名前」:任意、「タイプ」:パブリック、「コンパートメント」:使用コンパートメント、
「VCN」は、作成したVCN、「サブネット」はパブリックサブネットを選択して、
[ゲートウェイの作成]をクリック
[デプロイメントの作成]をクリック
「名前」:任意、「パス接頭辞」:/teamlist (今回は/teamlist)、コンパートメント:使用コンパートメント
を設定したら、[次]をクリック
「パス」:/v1 (今回は/v1)、「メソッド」:GET、「タイプ」:Oracle Functions、
「アプリケーション」:fn-f1site(『4-2.アプリケーションの作成』で作ったもの)、
「機能名」:f1_teamlist(『5.Oracle Functions 「チーム一覧ページ」作成』で作ったもの)を
設定して、[次]をクリック
[作成]をクリック
##6-2.API GatewayがOracle Functionsを使用できるように、動的グループ、ポリシーを作成
動的グループ、ポリシーを作成する詳細手順はこちら
まずは、動的グループ設定をします。
[アイデンティティとセキュリティ]-[動的グループ]をクリック
「名前」:任意、「説明」:任意、
「ルール」:使用コンパートメントのAPI Gatewayと指定 ※記載は下記に記載
[作成]をクリック
ALL {resource.type = 'ApiGateway', resource.compartment.id = '<functionsがあるコンパートメントのOCID>'}
次はポリシーの作成
「名前」:任意、「説明」:任意、「コンパートメント」:使用コンパートメント、
ポリシービルダでは、動的グループがコンパートメント内のファンクションを使用できると記載
※記載は下記に記載
Allow dynamic-group <動的グループ> to use functions-family in compartment <コンパートメント>
##6-3.API Gatewayのエンドポイントからアクセス
API Gatewayのエンドポイントからアクセスする詳細手順はこちら
「デプロイメント」の「エンドポイント」の[コピー]をクリックします
URLにアクセス(API Gatewayで設定したパスをつける)
※注意点は、パスを付けないといけません。パスは以下で設定しています。
『6-1.API GatewayからOracle Functions[f1_teamlist]を実行できる設定を行う』参照
https://ibxxx.apigateway.ap-tokyo-1.oci.customer-oci.com/teamlist/<API Gatewayで設定したパスを設定>
API Gatewayのエンドポイントからアクセス。画面が表示されることを確認。
#7.Oracle Functions 「チーム詳細ページ」作成
チーム詳細ページをOracle Functionsで作成します。
あわせてAPI Gatewayに作成するOracle Functionsを登録します。
※基本的な流れは、『5.Oracle Functions 「チーム一覧ページ」作成
』と同じです
Oracle Functions 「チーム詳細ページ」でも、作業ディレクトリに各種ファイルを作成していきます。
##7-1.「チーム詳細ページ」functions [f1_teamdetail]の作業ディレクトリを作成
「チーム詳細ページ」functions [f1_teamdetail]の作業ディレクトリを作成する詳細手順はこちら
##7-2.Oracle Instantclientのメディア、Autonomous Database walletを配置
Oracle Instantclientのメディア、Autonomous Database walletを配置する詳細手順はこちら
Oracle Instantclientの.zipを media フォルダにコピー、
walletファイルを dbwalletフォルダに解凍して格納
cd
mkdir f1_teamdetail/media
cp instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip f1_teamdetail/media
unzip Wallet_SERVERLESS.zip -d f1_teamdetail/dbwallet
##7-3.Pythonのメイン処理「func.py」を作成
Pythonのメイン処理「func.py」を作成する詳細手順はこちら
import io
import os
from fdk import response
import cx_Oracle
import logging
def handler(ctx, data: io.BytesIO=None):
try:
#GETでteamidを連携。Teamidを取得
#getvalue = "teamid=3"
getvalue = str(ctx.RequestURL())
pos = getvalue.find("teamid")
teamid = getvalue[pos+7:]
#logging.getLogger().info("function start")
#DB接続
username = "SCOTT"
password = "WElcome12345"
db_url = "serverless_medium"
#チーム名、画像URLを取得
sql="select * from team where team_id=" + str(teamid)
con = cx_Oracle.connect(username, password, db_url)
cur = con.cursor()
cur.execute(sql)
rows = cur.fetchall()
strteam =""
strimg=""
strdriver=""
resp=""
#Teamテーブルから情報取得
for r in rows:
strteam = str(r[1])
strimg = "<img src='" + str(r[2]) + "' height='250' width='350' >"
#F1ドライバ情報取得
sql="select driver_name from f1driver where team_id=" + str(teamid) + " order by driver_no "
cur.execute(sql)
rows = cur.fetchall()
for r in rows:
strdriver = strdriver + "<tr><td>" + str(r[0]) + "</td></tr>"
#HTML作成
html = ""\
"<html lang='ja'>"\
"<head><title>F1 Team Deatail</title></head>"\
"<meta charset='utf-8'>"\
"<body>"\
"<font size='5'><B>"\
" %s "\
"</B></FONT>"\
"<p>"\
" %s "\
"</p>"\
"<table border='1' style='border-collapse: collapse'>"\
"<tr ><th width='346'>ドライバー</th> </tr>"\
" %s "\
"</table>"\
"<br><button type='button' onclick=\"location.href='https://iba2rxxxxx.apigateway.ap-tokyo-1.oci.customer-oci.com/teamlist/v1'\">戻る</button>"\
"</body>"\
"</html>"
resp = html % (strteam,strimg,strdriver)
except Exception as e:
print('ERROR: Missing configuration keys, secret ocid and secret_type', e, flush=True)
return response.Response(
ctx,
response_data=resp,
headers={"Content-Type": "text/html"}
)
##7-4.requirements.txtに cx_Oracle を追加
requirements.txtに cx_Oracle を追加する詳細手順はこちら
fdk
cx_Oracle
##7-5.Dockerfile を新規追加
Dockerfile を新規追加する詳細手順はこちら
FROM oraclelinux:7-slim
WORKDIR /function
RUN groupadd --gid 1000 fn && adduser --uid 1000 --gid fn fn
RUN yum -y install python3 oracle-release-el7 && \
yum install -y unzip && \
yum install -y libaio-devel && \
rm -rf /var/cache/yum
ENV ORACLE_HOME=/function/instantclient_19_14
ENV LD_LIBRARY_PATH=/function/instantclient_19_14/lib:$LD_LIBRARY_PATH
ENV PATH=/function/instantclient_19_14:$PATH
ADD media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip /function/media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip
RUN unzip /function/media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip -d /function/tmp && \
mkdir /function/instantclient_19_14 && \
mv /function/tmp/instantclient_19_14 /function/instantclient_19_14/lib
COPY dbwallet/* /function/instantclient_19_14/network/admin/
RUN rm -f /function/media/instantclient-basiclite-linux.x64-19.14.0.0.0dbru.zip
ADD . /function/
RUN pip3 install --upgrade pip
RUN pip3 install --no-cache --no-cache-dir -r requirements.txt
RUN rm -fr /function/.pip_cache ~/.cache/pip requirements.txt func.yaml Dockerfile README.md
ENV PYTHONPATH=/python
ENTRYPOINT ["/usr/local/bin/fdk", "/function/func.py", "handler"]
##7-6.「チーム詳細ページ」Oracle Functions [f1_teamdetail]をデプロイ
「チーム詳細ページ」Oracle Functions [f1_teamdetail]をデプロイする詳細手順はこちら
##7-7.API Gateway に Oracle Functions [f1_teamdetail]を設定
API Gateway に Oracle Functions [f1_teamdetail]を設定する詳細手順はこちら
『6-1.API GatewayからOracle Functions[f1_teamlist]を実行できる設定を行う』で
作成した、API Gateway をクリック
「名前」:任意、「パス接頭辞」:/f1detail(今回は/f1detail) 、
「コンパートメント:使用コンパートメントを入力して、[次]をクリック
「パス」:/v1 (今回は/v1)、「メソッド」:GET、「タイプ」:Oracle Functions、
「アプリケーション」:fn-f1site(『4-2.アプリケーションの作成』で作ったもの)、
「機能名」:f1_teamdetailを設定して、[次]をクリック
作成した「f1detail」のエンドポイントの[コピー]をクリック
URLにアクセス(API Gatewayで設定したパスをつける)
※注意点は、パスを付けないといけません。パスは今回は「v1」で設定しています。
※「チーム詳細ページ」では、「チーム一覧ページ」で選択したTeamidを引数にしていますので
?teamidをつけています
https://iba2xxxxx.apigateway.ap-tokyo-1.oci.customer-oci.com/f1detail/v1?teamid=2
#8.「チーム一覧ページ」の「チーム詳細ページ」動作確認
「チーム一覧ページ」を開いて、選択したチームの詳細が表示されるかを確認
https://ibxxx.apigateway.ap-tokyo-1.oci.customer-oci.com/teamlist/v1
#最後に
Oracle Functionsを使用してWebサイト(動的)を作ることができました。
今回はDBのデータを参照するのみでしたが、
DB接続ができたのでデータ更新するページも作成できるはずです。
※2022年はRed Bullは、
「ORACLE Red Bull Racing(オラクル・レッドブル・レーシング)」として参戦です。