Pythonは今最も人気のある開発言語の1つです。そのシンプルな構文と参入障壁の低さから、ソフトウェア開発で頭角を現したい熱意溢れる初心者プログラマーにうってつけの言語です。

多くのフレームワークやライブラリが、Pythonアプリケーションの立ち上げと実行を容易にしています。DjangoFastAPIFlaskなどがその代表例です。Flaskフレームワークは、簡単なプロトタイピングや高いカスタマイズ性能を誇り、Python開発者を魅了しています。

今回のハンズオン形式の記事では、Flaskを使ってシンプルなデータベース接続型Pythonアプリケーションを開発する方法をご紹介します。

FlaskでPythonアプリをより簡単に

2010年に開発されたFlaskは、その使いやすさと柔軟性から、Pythonウェブアプリケーションの開発で人気を博します。無駄のないアーキテクチャで、必要な機能のライブラリを簡単に追加でき、同時に基本的な機能が網羅されています。このアプローチにより、Flask はシンプルなアプリケーションから複雑なシステムまで、多くのプロジェクトに利用できます。

Flaskには、ウェブアプリ開発をサポートするツールや機能がいくつも搭載されています。

  • HTTPリクエストとレスポンスを管理するライブラリとツール
  • リクエストを指定の関数にルーティングする機能
  • レンダリングテンプレートのサポート
  • データベースのサポート
  • 認証・認可システム

Python Flaskアプリの構築方法

実際にFlaskを使用してPythonウェブアプリを構築することで、ウェブアプリ開発にFlaskを使用する利点を体感することができます。その後、例えばKinstaのウェブアプリケーションホスティングサービスを使用してアプリケーションをビルド、デプロイし、同じくKinstaプラットフォーム上のマネージドデータベースに接続するといった公開方法があります。

Python Flaskアプリについての前提条件

今回の説明に従うには、以下のものが必要です。

Python Flaskのインストール

ターミナル(LinuxまたはmacOS)またはコマンドプロンプト(Windows)に移動します。flask_demoというディレクトリを作成してください。

作成したディレクトリに移動し、python3 -m venv venvコマンドを使ってPython仮想環境を作成します。ここでは、仮想環境をサポートするディレクトリの名前もvenvとします。

以下のいずれかのコマンドを使用して仮想環境を有効にします。

  • venvScriptsactivate Windowsの場合
  • source venv/bin/activate LinuxまたはmacOSの場合

次に、pip install flaskを実行して、pipを使ってFlaskをインストールします。

ターミナルでの作業は以下のようになります。

Python仮想環境の作成とFlaskインストール時のターミナル出力
ターミナルでPython Flaskアプリケーションの基礎を作る

ベースアプリケーションの構築

次に、ベースアプリケーションを作成し、ブラウザにコンテンツをレンダリングすることでその機能を確認します。

flask_demoディレクトリにdemo.pyというファイルを作成し、以下のコードを追加します。

from flask import Flask

app = Flask(__name__)

# ルート
@app.route('/')
def index():
    return "Happy Coding!"

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

このコードで、まず、flaskモジュールからFlaskをインポートし、appというインスタンスを作成します。その後、ユーザーがブラウザからアプリにアクセスしたときに「Happy Coding!」というテキストを返すルートの作成が行われます。最後に、スクリプトが起動したら開発サーバーを実行します。

ターミナルでflask --app demo runを実行して、アプリケーションを起動します。--appは実行するアプリケーションの場所を指定します。ここではdemo.pyファイルになります。

Python Flaskアプリにテンプレートを追加する

アプリにテンプレートを追加することで、コンテンツを調整することができます。まず、アプリケーションのルートにtemplatesというディレクトリを作ります。次に、templatesディレクトリに移動し、以下のHTMLコードを含むindex.htmlファイルを作成します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HomePage</title>
</head>
<body>
    <h3>Flask Demo Application</h3>
    <p>My name is John Doe - learning about Application Deployment!</p>
</body>
</html>

demo.pyで、flaskモジュールからrender_templateをインポートし、route関数内でindex.htmlテンプレートを次のようにレンダリングします。

from flask import Flask, render_template

app = Flask(__name__)

# ルート
@app.route('/')
def index():
    return render_template('index.html')

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

次に、ローカル環境でflask --app demo runを実行してアプリケーションを配信します。ターミナルで確認できるローカルアドレスを使用して、ブラウザでアプリを起動します。すると、以下のように表示されるはずです。

Flaskアプリケーションの初期段階を表示するウェブブラウザのスクリーンショット
ウェブブラウザでPython Flaskアプリを起動したところ

ローカルデータベースへの接続

アプリケーションのコンテンツを保存するローカルデータベース(MySQL)への接続を構築します。

FlaskアプリケーションをMySQLに接続するには、以下をインストールします。

  • flask_mysqldb:FlaskのMySQLコネクタ(pip install flask_mysqldb使用)
  • Python-dotenv:環境変数の読み込み(pip install python-dotenv使用)
  • Python MySQLコネクタ(pip install mysql-connector-python使用)
  • MySQL依存関係(pip install mysqlclient使用)

続いてはデータベース作成です。MySQL Workbenchに移動しましょう。データベースにアクセスしテーブルを作成する権限を持つデータベースユーザーを追加します。

アプリケーションのルートディレクトリに.envファイルを作成し、データベース接続の詳細情報を保持します。このテンプレートに、以下のようにデータベースユーザーの資格情報とデータベース名を追加します。

DB_HOST="localhost"
DB_USER="your-db-user"
DB_PASSWORD="your-db-password"
DB_NAME="your-db-name"

調整後のdemo.pyスクリプトでは、MySQLコネクタをインポートし、Python-dotenvを使用して.envファイルの環境変数キーを読み取ります。このdemo.pyスクリプトで、データベースにpersonsという名前のテーブルが存在するかどうかもチェックされ、存在しない場合には作成の上で入力に進みます。

import os
from flask import Flask, render_template
from flask_mysqldb import MySQL

from dotenv import load_dotenv
load_dotenv()

app = Flask(__name__)

app.config['MYSQL_HOST'] = os.getenv("DB_HOST")
app.config['MYSQL_USER'] = os.getenv("DB_USER")
app.config['MYSQL_PASSWORD'] = os.getenv("DB_PASSWORD")
app.config['MYSQL_DB'] = os.getenv("DB_NAME")

mysql = MySQL(app)

@app.route('/')
def index():
    cursor = mysql.connection.cursor()

    cursor.execute("SHOW TABLES LIKE 'persons'")
    result = cursor.fetchone()

    if not result:
        cursor.execute(''' CREATE TABLE persons (id INTEGER, firstname VARCHAR(20), lastname VARCHAR(20)) ''')
        cursor.execute(''' INSERT INTO persons VALUES(1, 'John', 'Doe') ''')
        cursor.execute(''' INSERT INTO persons VALUES(2, 'Milly', 'Winfrerey') ''')
        mysql.connection.commit()

    cursor.execute('SELECT * FROM persons')
    entry = cursor.fetchall()
    cursor.close()
    return render_template('index.html', entry=entry)

Flaskをインスタンス化した後、上のコードが環境変数を使ってアプリケーションのルートにある.envファイルからデータベースの属性を取得します。

そして、MySQLをインスタンス化し、Flaskと関連付けます。indexルートにカーソルオブジェクトを作成されます。次に、データベースにpersonsという名前のテーブルがあるかどうかをチェックします。見つからない場合は、idfirstnamelastname属性でテーブルを作成し、2行のデータを挿入します。

次の3行は、personsテーブルから全ての行を選択し、結果を取得するSQLコマンドを実行するものです。カーソルオブジェクトは終了し、クエリの結果はテンプレートでレンダリングするためにコンテキスト変数entryとして渡されます。

データベースクエリの結果を処理できるように調整したindex.htmlテンプレートファイルを以下に示します。

<!DOCTYPE html><html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HomePage</title>
</head>
<body>
    <h3>Flask Demo Application</h3>
    {% for e in entry %}
        <p>My name is {{e[1]}} {{e[2]}} - learning about Application Deployment!</p>
    {% endfor %}
</body>
</html>

アプリケーションを実行し、MySQL Workbenchに戻ってデータを確認します。以下のようになるはずです。

MySQL Workbenchのクエリ結果のスクリーンショット
MySQL Workbenchのpersonsテーブルのクエリ結果

テーブルにクエリを実行すると、アプリケーションによって生成された2つのエントリが返されます。これで、アプリケーションは次のようなデータベース由来のコンテンツをブラウザにレンダリングすることになります。

データベースから生成されたコンテンツを示すスクリーンショット
データベースが生成したコンテンツをブラウザで確認する

Python FlaskアプリをKinstaにデプロイする方法

アプリケーションがローカルで無事稼働したので今度は、Kinstaのホスティングを使って公開してみましょう。Kinstaのウェブアプリケーションホスティングマネージドデータベースホスティングを組み合わせることで、このアプリをクラウド上で公開することができます。どちらも無料からお試しいただけます。

デプロイに向けたPythonプロジェクトの準備

Kinstaのウェブアプリケーションホスティングでは、好みのGitサービスからコードをデプロイ可能です。次のステップとして、その経路をサポートするようにアプリケーションの環境を設定します。これにより、Kinstaで必要なすべての依存関係を持つアプリケーションをデプロイできるようになります。

flask_demoプロジェクトのルート内に新規ディレクトリを作成することから始めましょう。これにmyappという名前をつけます。そしてtemplatesディレクトリとdemo.pyファイルをmyappに移動します。

myappディレクトリの中に、以下の内容でwsgi.pyファイルを作成してください。

from myapp.demo import app as application

if __name__ == "__main__":
    application.run(debug=True)

Kinstaのビルドプロセスで、アプリケーション生成にpipを使用できます。プロジェクトのルートディレクトリにあるrequirements.txtファイルを使用して、アプリの依存関係を本番環境のpipに渡すことが可能です。

venv仮想環境とflask_demoルートディレクトリで作業しながら、次のコマンドでプロジェクト固有のrequirements.txtファイルを生成します。

pip freeze > requirements.txt

生成されたテキストファイルの内容は次のようになります。

blinker==1.7.0
click==8.1.7
Flask==3.0.0
Flask-MySQLdb==2.0.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
mysql-connector-python==8.2.0
mysqlclient==2.2.1
protobuf==4.21.12
python-dotenv==1.0.0
Werkzeug==3.0.1

.envファイルをデータベースシークレットとともに本番サーバーに送信することはありません。python-dotenvライブラリが本番サーバーで.envを読み込む必要はないため、requirements.txtから参照を削除し、demo.pyの該当する行を削除(またはコメントアウト)します。

from dotenv import load_dotenv
load_dotenv()

プロジェクトにPython WSGI HTTPサーバーを追加する

上記の要件で1つ欠けているのが、本番環境でHTTP経由でアプリケーションを提供する方法です。ローカルマシンで使う開発用サーバーでは不十分です。このプロジェクトでは、アプリとKinstaのNginxウェブサーバーの間にWeb Server Gateway Interface(WSGI)パッケージのGunicornを使用します。

以下のように仮想環境内にインストールすることで、プロジェクトにGunicornの要件を追加することができます。

pip install gunicorn

Gunicornがインストールされたら、pipを使用してrequirements.txtを再度生成します。

Gunicornをローカルにインストールする代わりに、requirements.txtを編集して、次のようなエントリを追加することもできます。

gunicorn==21.2.0

WSGIサーバーの土台を整えるには、プロジェクトのルートディレクトリにProcfileという名前のファイルを作成し、次のコードを追加します。

web: gunicorn myapp.wsgi

これが、本番環境でのアプリのstartコマンドの元になります。

プロジェクトをGitに対応させる

調整後のディレクトリ構造をKinstaでデプロイする準備ができました。しかし、すべてのファイルを本番環境に公開するのは避けましょう。プロジェクトのルートに、次のような内容の.gitignoreファイルを作成します。

/venv
.env

これで、venvディレクトリ内のファイルと.env内のローカルデータベースのシークレットがGitホストにアップロードされないようになります。

ローカルのGit環境を立ち上げ、好みのツールを使ってコードを Gitサービスにプッシュできます。

Python FlaskアプリをKinstaにデプロイする

コントロールパネル「MyKinsta」にログインし、まだの場合には、KinstaでのGitサービスへのアクセスを許可します。アプリケーションを追加する手順に従って処理を行い、Flaskプロジェクトコード(Gitホスト上のリポジトリとブランチ)を選択します。

ビルド環境を設定する際には、「Buildpacksを使用してコンテナイメージを設定」を選択し、その他の設定はデフォルトのままにします(startコマンドProcfileですでに定義されているため、指定しません)。

ビルド環境を設定するためのMyKinstaインターフェースのスクリーンショット
Buildpacksでアプリケーションのコンテナイメージをセットアップする

お支払い情報を確認したら(無料で利用を始められます)、「今すぐデプロイする」ボタンをクリックします。以下のようにログビューアで進行状況を確認可能です。

Python Flaskアプリデプロイ時のログエントリーのスクリーンショット
Python Flaskアプリのデプロイ状況をログで確認する

Python Flaskアプリにデータベースを追加する

Kinstaには、Redis、PostgreSQL、MariaDB、MySQLという4つのマネージドデータベースオプションがあります。この説明では、MySQLデータベースを利用します。

データベースを追加する方法を参考に、Flaskアプリケーションと同じデータセンターを選択してください。

データベースを作成したら、利用可能なDBサーバーの一覧から選択し、「概要」タブの「内部接続」セクションまでスクロールします。「接続を追加」ボタンをクリックすると、同じデータセンター所在地にあるFlaskアプリケーションサービスが選択可能になります。

MyKinsta内部データベース接続を追加するダイアログのスクリーンショット
データベースを作成した後、アプリケーションに内部接続を追加

接続設定の際には、「アプリケーションへの環境変数の追加」にチェックを入れてください。これにより、データベースのシークレットキーを伝える環境変数が表示され、.envファイルを必要とせずに安全に処理されます。

データベース認証情報用の環境変数を追加するダイアログのスクリーンショット
データベースへの内部接続に環境変数を適用する

上のダイアログの一番下にある「ランタイムで利用可」と「ビルドプロセスで利用可」はデフォルトで有効になっています。

最終的に「接続を追加」ボタンをクリックすると、データベースアクセスに必要な環境変数がMyKinstaの「アプリケーション」ダッシュボードの「設定」に反映されます。

データベースからアプリケーションに渡される環境変数を示すMyKinstaダイアログのスクリーンショット
Python Flaskアプリにデータベース環境変数をわたす

これで、今後、機能の拡張後にアプリケーションを再ビルドしても、データベース接続が維持されます。

スクリーンショット(Kinstaプラットフォーム上で稼動しているPython Flaskアプリケーション)
Python FlaskアプリケーションがKinstaプラットフォーム上で動作している様子

これで無事にPython Flaskアプリケーションを作成し、Kinstaプラットフォームにデプロイすることができました。

まとめ

Flaskはカスタマイズ性能の高いフレームワークです。これを使ってPythonアプリケーションを簡単に作成することができます。FlaskアプリケーションのデプロイにKinstaを使用すると、さらにこのプロセスが容易になります。

今回の記事では、ローカルの開発環境でシンプルなデータベース接続型アプリケーションを構築し、Kinstaのウェブアプリケーションホスティングデータベースホスティングを使って公開する方法を順を追ってご紹介しました。

Kinstaのすぐに使える活用例もあわせてご覧ください。

Steve Bonisteel Kinsta

Kinstaのテクニカルエディター。救急車や消防車を追いかける記者としてキャリアをスタート。1990年代後半からインターネット関連の技術情報を担当している。