ConoHa WINGでPython (FastAPI + SQLAlchemy)を使う
当ブログはConoHa WINGを使って公開していますが、せっかくWebサーバー(Apache + nginx)とデータベース(MySQL)が提供されているのにそれを利用しないのは勿体ないので、ConoHa WING上で自作Webアプリを動かせないかと考えていました。
ConoHa WINGは共用サーバーでサービスを提供しており、WordPressの運用に強いサーバー環境が整っています。そのため、PHP(Laravelも使用可能)で開発したWebアプリは動かしやすいのですが、PythonでFastAPIやSQLAlchemyを使って開発したWebアプリを動かすにはいくつか課題がありました。
本記事では、FastAPIとSQLAlchemyを使ったWebアプリをConoHa WING上で動くようにしたときの手順について説明します。
ConoHa WINGで利用できるPythonのバージョン
Section titled “ConoHa WINGで利用できるPythonのバージョン”ConoHa WINGは、PHPの他にもプログラミング言語をいくつか用意しています。
sshでログインして、インストールされているPythonのバージョンを確認してみると、以下のバージョンが用意されていることが分かりました。
[c********@web**** ~]$ ls /opt/alt/|grep pythonpython-internalpython27python311python36python37python38この記事を書いている時点でPython 3.11が用意されていますので、これを使って環境を構築します。
サンプルプログラムのダウンロードと環境構築
Section titled “サンプルプログラムのダウンロードと環境構築”FastAPIとSQLModelを使った練習用Webアプリ(location-logger-fastapi)を開発してGitHubに公開していますので、これをConoHa WINGのサーバーにcloneします。
mkdir -p ~/workdir/cd ~/workdir/git clone https://github.com/yamakox/location-logger-fastapi.gitさらに、Pythonのソースコードの入ったフォルダー(backend)に移動して、Python 3.11の仮想環境を作成します。
cd location-logger-fastapi/backend/opt/alt/python311/bin/python3 -m venv .venvConoHa WINGのコントロールパネル → サーバー管理 → ドメインの画面を開き、+ドメインボタンでWebアプリ用のサブドメインを追加しておいてください。
補足: location-logger-fastapiについて
location-logger-fastapiは、以下の構成でWebアプリを実装しています。
flowchart LR
ui["`**Vueアプリ**
地図・地名表示、
現在位置の取得`"]
www["`**WWWサーバー**
Vueアプリ配信`"]
api["`**FastAPI**
REST APIの実装
+
**SQLModel**
SQLAlchemy経由でDB操作`"]
db["`**MySQL**
位置情報の記録`"]
subgraph client [Webブラウザ]
direction TB
ui
end
subgraph server [サーバー]
direction TB
www
api
end
subgraph database [データベース]
direction TB
db
end
ui <--> www
ui <--> api
api <--> dbVueアプリのスクリーンショットは以下のとおりです。
課題: ConoHa WINGでFastAPIアプリを動かす方法
Section titled “課題: ConoHa WINGでFastAPIアプリを動かす方法”FastAPIで開発したアプリはuvicornなどのASGI Webサーバーを使って動かすことが一般的と思いますが、共用サーバーのConoHa WINGでは、独自のWebサーバーを動かす方法は提供されていないと思います。
そのため、ConoHa WINGが用意しているApache経由でFastAPIのアプリを呼び出せるようにします。
location-logger-fastapiでは./public/index.cgiを作って、ApacheからCGIとしてFastAPIのアプリを呼び出せるようにしています。具体的には、CGIスクリプトの中でASGIMiddlewareとCGIHandlerを使ってFastAPIアプリを実行します。
#!/home/c*******/workdir/location-logger-fastapi/backend/.venv/bin/python3
from dotenv import load_dotenvfrom pathlib import Path
# index.cgiと同じ場所に置いてある.envファイルを読み込むenv_path = Path(__file__).parent.resolve() / '.env'load_dotenv(str(env_path))
from a2wsgi import ASGIMiddlewarefrom wsgiref.handlers import CGIHandlerfrom location_logger import create_app
# FastAPIには`/index.cgi/パス`が渡されるapp = create_app(base_url='/index.cgi')app = ASGIMiddleware(app)
CGIHandler().run(app)create_app関数は./backend/location_logger/__init__.pyで実装しており、base_url引数の値をFastAPIクラスの初期化時にroot_pathパラメータに渡しています。
from fastapi import FastAPIfrom . import api
def create_app(base_url: str = '') -> FastAPI: app = FastAPI(root_path=base_url) # `/index.cgi`をroot_pathとする app.include_router(api.v1.create_router()) # `api`モジュールの中でAPIエンドポイントを作成する return app課題: 依存関係のあるPythonパッケージのインストール
Section titled “課題: 依存関係のあるPythonパッケージのインストール”sshでログインして、ConoHa WINGのPython仮想環境に依存関係のあるPythonパッケージをインストールするときに問題が発生しました。
[c********@web**** backend]$ source .venv/bin/activate(.venv) [c********@web**** backend]$ pip3 install .
(中略)
コンパイルを停止しました。 error: command '/usr/bin/g++' failed with exit code 1 ---------------------------------------- ERROR: Failed building wheel for greenletSuccessfully built location-loggerFailed to build greenletERROR: Could not build wheels for greenlet, which is required to install pyproject.toml-based projectsgreenletはSQLAlchemyに依存関係のあるパッケージですが、greenletのインストール時にソースコードからのビルドが動いてしまい、コンパイルエラーが発生してインストールに失敗します。
そこで、ソースコードからビルドしないように、greenletを--no-buildオプション付きでインストールします。
(.venv) [c********@web**** backend]$ pip3 install --no-build greenlet
(中略)
Downloading greenlet-3.2.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (643 kB) |████████████████████████████████| 643 kB 65.9 MB/sInstalling collected packages: greenletSuccessfully installed greenlet-3.2.5(中略)の部分では、新しいバージョンから順にインストールしようとしてエラーが発生し、段々と古いバージョンのパッケージを試している様子が伺えます。
greenlet 3.2.5がインストールできたので、残りのパッケージをインストールします。
(.venv) [c********@web**** backend]$ pip3 install .
(中略)
Successfully built location-loggerInstalling collected packages: (以下略)FastAPIアプリのインストールは無事成功しました。
(.venv) [c********@web**** backend]$ python3 -m location_logger.db init
# テーブルができていることを確認する(.venv) [c********@web**** backend]$ source .env(.venv) [c********@web**** backend]$ mysql -h${DB_HOST} -P${DB_PORT} -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME}
mysql> SHOW TABLES;+----------------------+| Tables_in_*****_**** |+----------------------+| clients || locations |+----------------------+2 rows in set (0.00 sec).envファイルを作成してデータベースの初期化コマンドを実行すると、正常にテーブルが作成できましたので、これでFastAPIとSQLAlchemyを使ったアプリが動く環境を整えることができたと判断します。
課題: Node.jsはConoHa WINGに用意されていない
Section titled “課題: Node.jsはConoHa WINGに用意されていない”ConoHa WINGではプログラミング言語をいくつか用意されていますが、Node.jsやnpmは提供されていません。
そのため、ローカル環境でVueアプリのビルドを行い、scpやrsyncを使ってサーバーのpublic_html/<サブドメイン名>フォルダーに転送します。
./public/index.cgiもローカル環境で作成して、Vueアプリのビルド成果物の中に含めます。
# Vueアプリのビルドnpm inpm run build
# dist配下のファイルをコピーするscp -P <ポート番号> -r ./dist/* ./dist/.[!.]* <レンタルサーバのユーザ名>@<レンタルサーバ名>:/home/<ユーザー名>/public_html/<サブドメイン名>これで、Vueアプリの配信とFastAPIで実装したAPIエンドポイントの公開を、ConoHa WINGのApache経由でできるようになりました。ブラウザでVueアプリを表示して、FastAPIで実装したAPIを使って取得した値(CIDとVersion)が表示されていれば、正常に動作しています。
Python(FastAPI+SQLAlchemy)を使ったWebアプリは、index.cgiを作成してConoHa WINGで動かすことができました。
ConoHa WINGのCloudLinux環境では、Pythonパッケージのインストールに失敗することもありますが、--no-buildオプションで回避できる可能性があります。
flowchart LR
ui["`**Vueアプリ**
地図・地名表示、
現在位置の取得`"]
www["`**index.htmlなど**
Vueアプリ配信`"]
api["`**index.cgi**
FastAPI + SQLAlchemy`"]
db["`**MySQL**
位置情報の記録`"]
subgraph client [Webブラウザ]
direction TB
ui
end
subgraph public_html [public_html/ドメイン名]
www
api
end
subgraph server [ConoHa WING]
direction LR
public_html
db
end
ui <--> www
ui <--> api
api <---> db
APIを呼び出すたびにindex.cgiが動くのでuvicornを使った場合と比べるとレスポンスが良くありませんが、それでも自作Webアプリを公開できる可能性が広がったことは意義があると思います。