1
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?

FlaskアプリケーションをGoogle App Engineにデプロイし、Cloud SQLに接続する方法

Last updated at Posted at 2024-10-17

この記事では、Flaskを使用したウェブアプリケーションをGoogle App Engineにデプロイし、Cloud SQL(PostgreSQL)データベースに接続する手順を詳しく説明します。ウェブアプリの詳細については、別の記事で解説する予定です。

GCP(Google Cloud Platform)は初回でアカウントを作成すると、90日間で300ドル分貰えるのでおすすめです。また他にも、無料枠が多いのも特徴です。詳細はこちら

こちらが今回作成した簡単なwebアプリになります。UI,UXがこだわりきれてないのですが、カメラを起動して、ユーザーの手を認識して、ユーザーがコンピュータの指示に従うとスコアが増えていくようになっています。ぜひ、遊んで、スコアをリーダーボードにあげてみてください。

前提条件

以下は他の記事でも詳しく解説されているので、そちらをみてください。
・Google Cloud Platform(GCP)アカウントを持っていること
Cloud SDKがインストールされていること
・Python 3.9 以上がインストールされていること

ステップ1: プロジェクトのセットアップ

1.1 プロジェクトディレクトリの作成

まず、新しいプロジェクトディレクトリを作成してここにつくってWEBアプリのコードをかいていきます。

mkdir janken-game
cd janken-game

1.2 必要なパッケージのインストール

requirements.txt ファイルを作成し、以下の内容を追加します。
以下は例です。

Flask==2.3.3
SQLAlchemy==1.4.36
gunicorn==20.1.0
cloud-sql-python-connector[pg8000]==1.2.2

ステップ2: Flaskアプリケーションの作成

ウェブアプリの詳細な実装については、別の記事で解説する予定です。

2.1 アプリケーションコードの作成

app.py ファイルを作成し、以下のコードを追加します。

import os
from flask import Flask, render_template, request, jsonify, redirect, url_for
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import Base, LeaderboardEntrySingle, LeaderboardEntryBoth

# Cloud SQL Python Connector のインポート
from google.cloud.sql.connector import Connector
import pg8000

app = Flask(__name__)

# 環境変数からデータベース接続情報を取得
db_user = os.environ.get("DB_USER")
db_password = os.environ.get("DB_PASS")
db_name = os.environ.get("DB_NAME")
cloud_sql_connection_name = os.environ.get("CLOUD_SQL_CONNECTION_NAME")  # app.yaml で設定

# Cloud SQL Python Connector を初期化
connector = Connector()

def getconn():
    conn = connector.connect(
        cloud_sql_connection_name,
        "pg8000",
        user=db_user,
        password=db_password,
        db=db_name,
    )
    return conn

# SQLAlchemy エンジンを作成
engine = create_engine(
    "postgresql+pg8000://",
    creator=getconn,
)

Base.metadata.create_all(engine)
DBSession = sessionmaker(bind=engine)
session = DBSession()


# ルートエンドポイント
@app.route('/')
def index():
    return render_template('index.html')

# 片手モードのゲーム開始エンドポイント
@app.route('/start_game_single_hand')
def start_game_single_hand():
    return render_template('game_single_hand.html')

# 両手モードのゲーム開始エンドポイント
@app.route('/start_game_both_hands')
def start_game_both_hands():
    return render_template('game_both_hands.html')

# スコアの受け取りエンドポイント(片手モード)
@app.route('/submit_score_single', methods=['POST'])
def submit_score_single():
    data = request.get_json()
    username = data.get('username')
    score = data.get('score')

    if username and score is not None:
        entry = LeaderboardEntrySingle(username=username, score=score)
        session.add(entry)
        session.commit()
        return jsonify({'status': 'success'})
    else:
        return jsonify({'status': 'error'}), 400

# リーダーボード表示エンドポイント(片手モード)
@app.route('/leaderboard_single')
def leaderboard_single_hand():
    leaderboard = session.query(LeaderboardEntrySingle).order_by(LeaderboardEntrySingle.score.desc()).all()
    return render_template('leaderboard_single.html', leaderboard=leaderboard)

# スコアの受け取りエンドポイント(両手モード)
@app.route('/submit_score_both', methods=['POST'])
def submit_score_both():
    data = request.get_json()
    username = data.get('username')
    score = data.get('score')

    if username and score is not None:
        entry = LeaderboardEntryBoth(username=username, score=score)
        session.add(entry)
        session.commit()
        return jsonify({'status': 'success'})
    else:
        return jsonify({'status': 'error'}), 400

# リーダーボード表示エンドポイント(両手モード)
@app.route('/leaderboard_both')
def leaderboard_both_hand():
    leaderboard = session.query(LeaderboardEntryBoth).order_by(LeaderboardEntryBoth.score.desc()).all()
    return render_template('leaderboard_both.html', leaderboard=leaderboard)

if __name__ == '__main__':
    app.run(debug=True)

2.2 モデルの定義

models.py ファイルを作成し、データベースのモデルを定義します。
(以下は例です)

python# models.py
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class LeaderboardEntrySingle(Base):
    __tablename__ = 'leaderboard_single'
    id = Column(Integer, primary_key=True)
    username = Column(String)
    score = Column(Integer)

class LeaderboardEntryBoth(Base):
    __tablename__ = 'leaderboard_both'
    id = Column(Integer, primary_key=True)
    username = Column(String)
    score = Column(Integer)

ステップ3: Cloud SQL(PostgreSQL)インスタンスの作成

3.1 インスタンスの作成

  1. Google Cloud Console にアクセスし、左側のメニューから「SQL」を選択します。
  2. インスタンスを作成」をクリックし、「PostgreSQL」を選択します。
  3. インスタンスID、パスワード、リージョン(例: asia-northeast2)を設定します。
  4. 「作成」をクリックしてインスタンスを作成します。

3.2 データベースとユーザーの作成

  1. インスタンスが作成されたら、その詳細ページに移動します。
  2. 「データベース」タブで、新しいデータベース(例: janken_db)を作成します。
  3. 「ユーザー」タブで、新しいユーザー(例: flask_user)を作成し、パスワードを設定します。

3.3 接続情報の取得

  1. インスタンス接続名(例: your-project-id:region:instance-id)をメモします。
  2. Private IP を使用する場合は、「接続」タブでPrivate IPを有効にします。

ステップ4: app.yaml の作成

App Engineの設定ファイル app.yaml を作成し、以下の内容を追加します。

runtime: python39
entrypoint: gunicorn -b :$PORT app:app

env_variables:
  DB_USER: "flask_user"  # データベースユーザー名
  DB_PASS: "your-password"  # データベースパスワード
  DB_NAME: "janken_db"  # データベース名
  CLOUD_SQL_CONNECTION_NAME: "your-project-id:region:instance-id"  # インスタンス接続名

vpc_access_connector:
  name: "projects/your-project-id/locations/asia-northeast2/connectors/serverless-connector"

automatic_scaling:
  target_cpu_utilization: 0.65
  max_instances: 2

handlers:
- url: /static
  static_dir: static

- url: /.*
  script: auto

注意: your-password や your-project-id:region:instance-id などは、あなたの環境に合わせて置き換えてください。

ステップ5: サービスアカウントの権限設定

5.1 Cloud SQL Admin APIの有効化

  1. Google Cloud Console で左上のメニューから「APIとサービス」 > 「ライブラリ」を選択します。
  2. 「Cloud SQL Admin API」を検索し、選択します。
  3. 「有効にする」をクリックします。

5.2 サービスアカウントに役割を付与

  1. 左側のメニューから「IAMと管理」 > 「IAM」を選択します。
  2. サービスアカウント your-project-id@appspot.gserviceaccount.com を探します。
  3. 「編集」をクリックし、「+役割を追加」を選択します。
  4. 「Cloud SQL クライアント」の役割を選択し、追加します。
  5. 「保存」をクリックします。

ステップ6: アプリケーションのデプロイ

自分の作成したフォルダで、以下のコマンドを実行して、アプリケーションをデプロイします。

gcloud app deploy

デプロイが成功したら、次のコマンドでアプリケーションをブラウザで開きます。

gcloud app browse

ステップ7: トラブルシューティング

7.1 ログの確認

問題が発生した場合は、以下のコマンドでログを確認できます。

gcloud app logs tail -s default

7.2 よくある問題と解決策

権限エラー: サービスアカウントに必要な役割(「Cloud SQL クライアント」など)が付与されていることを確認します。

APIが有効化されていない: 「Cloud SQL Admin API」が有効になっていることを確認します。

接続エラー: CLOUD_SQL_CONNECTION_NAME が正しく設定されていることを確認します。

1
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
1
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?