PythonAnywhereにWebアプリを公開する

Pythonで作ったアプリを気軽に公開できる環境というのは、意外とありません。
大概のレンタルサーバはPHPが動けば良いという感じで、シェルに入るとRubyやPython、Perlが動くけれど、あくまでCGIという感じで、例えばPythonでFlaskで作ったアプリを簡単に動かせるレンタルサーバはなかなかないのです。

そんな中、AnacondaがやっているPythonAnywhereは、かなりおすすめ。Beginnerプランだと無料で使えます。ユーザー登録もメールアドレスさえあれば、それだけでOK。クレジットカードも不要です。

公開したいアプリ

Flaskで作ったPythonアプリがあることにします。データベースも使っているアプリなので、公開するにはMySQLとかが必要なのですが、PythonAnywhereはBiginnerプランでもMySQLが使えるので大丈夫です。

ざっと、こんな画面のアプリです。

アプリはGitHubのプライベートリポジトリとしてPUSHされています。

アプリの公開

Web Appsを作成する

PythonAnywhereのDashboardから、Web Appsを新規作成します。

Add a new web appをクリックします。

あとはウィザードに沿って操作します。

ここでFlaskをクリックします。

使うPythonのバージョンを選択します。今回は、Python 3.10を選択しました。

今回作っているアプリは、app.pyがエントリポイントになっているので、Pathの最後をapp.pyにしておきます。

これでWeb Appが作成できました。PythonAnywhereのユーザー名をサブドメインとしたURLが発行され、このURLにアクセスすると、公開したアプリが表示されるようになります。

ちなみに、デフォルトでは「Hello from Flask!」とだけ表示されるはずです。

ConsoleでGitリポジトリをクローンする

PythonAnywhereでは、Consoleが使えます。サーバに入ってシェルでの操作ができるわけですね。

メニューからConsoleをクリックし、Bashをクリックするとシェルが開きます。

lsしてみると、mysiteというディレクトリが見えます。ここに、先ほどWeb Appsでアプリを作ったファイルが入っています。

GitHubからプライベートリポジトリをクローンするには、何らかの方法でGitHubの認証をパスする必要があります。

ポピュラーなのは、SSHキーペアを作成し、公開鍵をGitHubに登録しておく方法です。GitHubのアカウントレベルで公開鍵を登録しても良いですし、使用するリポジトリのSettings画面からDeploy keysを選択し、そのリポジトリだけで有効な公開鍵を登録するという方法でも構いません。

まずは、ログインしているシェルでSSHキーペアを作成します。作成したSSHキーペアは、~/.sshに保存されますが、シェルからログアウトしてもちゃんと保持されているので問題ありません。

ssh-keygen

ウィザードに沿ってキーペアを作成した後、~/.ssh/id_rsa.pubを表示し、表示された内容をコピーして、GitHub側に登録します。

cat .ssh/id_rsa.pub

公開鍵の登録が完了した後、シェルの画面に戻り、公開したいアプリのリポジトリをクローンします。python-flaskというリポジトリです。
ただ、下記のリポジトリは私のプライベートリポジトリです。ご自身で使用されているリポジトリに変える必要があります。

git clone [email protected]:inoccu/python-flask.git

クローンが完了すると、~/python-flaskというディレクトリが出来ているはずです。
先ほど、Web Appsの設定で、~/mysiteに公開したいアプリが入っているようにしたので、既に作成されている~/mysiteはバックアップを取り、~/python-flaskからシンボリックリンクを作成します。

mv mysite mysite.bak
ln -s python-flask mysite

ここまで作業したら、PythonAnywhereのWeb Appsの画面に戻り、Reloadを行います。このReloadを行わないとアプリの更新が反映されません。

これで、自分のPythonAnywhereのアプリのURLを開くと、自分のアプリの画面が出てくるはずです。(表示する画面がデータベース接続を必要としない場合)

データベース(MySQL)の使用

PythonAnywhereではMySQLも使用できます(Postgresも使用できるようです)。
DashboardのメニューからDatabasesを開きます。

最初はMySQLのパスワードを設定する画面が開くので、使用したいパスワードをセットして、Initialize MySQLボタンをクリックします。

しばらく待っているとMySQLの接続情報が表示されます。
Database host addressが接続先のアドレス、Usernameは接続に使用するユーザ名です。その名のとおりですね。パスワードは先ほど設定したものなので、これを自分のプログラムの方に設定するとMySQLに接続できます。

あと、データベースの作成もしておきます。
表示されているMySQL settingsの画面の真ん中くらいに、Create databaseというフォームがあるので、ここに作りたいデータベース名を入力してCreateボタンをクリックします。

データベース名としてcalcと入力しても、実際に作成されるデータベース名はinoccu$calcのようにユーザー名が入ったものになるので注意が必要です。

データベースの準備はできたとして、テーブルの作成をする必要があります。
既に開発環境に存在しているであろうデータベースをエクスポートし、PythonAnywhere側のMySQLにインポートするのが最も簡単です。

例えば、WindowsでHeidiSQLを使っているなら、エクスポートしたいデータベースを右クリックして「データベースをSQLとしてエクスポート」を選択し、テーブルの方にだけ「作成」にチェックを入れてエクスポートすると良いでしょう。

エクスポートしてできたsqlファイルは、PythonAnywhereのFiles画面を開いてアップロードすると良いでしょう。

実際のインポートは、シェルからこのようにします。sqlファイルをアップロードしたディレクトリで操作するようにしてください。(後でsourceコマンドを使用する際にパスを指定していないため。)
ここでは、パスワードの設定は不要なようです。

mysql -h <PythonAnywhereのアカウント名>.mysql.pythonanywhere-services.com -u <PythonAnywhereのアカウント名>

MySQLにログインした後は、このようにします。

use <PythonAnywhereのアカウント名>$calc
source calc.sql
exit

useコマンドでデータベースの切り替えを行い、sourceコマンドで先ほどアップロードしたsqlファイルの名前を指定します。
これでインポートが完了するはずです。

DB接続情報を.envに逃がす

アプリの更新とリリースを繰り返す場合、DB接続情報を都度、サーバ側で書き換えるのは大変なので、.envファイルを使う方法があります。
.envファイルを使うと、接続情報を外のファイルに逃がしておけます。

python-dotenvの導入

pip install python-dotenv

.envファイルの作成

下記のような.envファイルをapp.pyと同じディレクトリに作成します。

MYSQL_HOST=<PythonAnywhereのアカウント名>.mysql.pythonanywhere-services.com
MYSQL_USER=<PythonAnywhereのアカウント名>
MYSQL_PASSWORD=<パスワード>
MYSQL_DATABASE=<PythonAnywhereのアカウント名>$calc

.envはGit管理させないため、.gitignoreに下記を追記します。

.env

app.pyの編集

app.pyに下記を追記します。

from dotenv import load_dotenv # これを追加
import os # これを追加
from flask import Flask, g

load_dotenv() # これを追加
app = Flask(__name__)

app.pyのDB接続部分をこのようにします。
(下記はDBコネクションをgにセットしている場合。)

g.db = mysql.connector.connect(
  host=os.environ['MYSQL_HOST'],
  port=3306,
  user=os.environ['MYSQL_USER'],
  password=os.environ['MYSQL_PASSWORD'],
  database=os.environ['MYSQL_DATABASE'])        

動作確認

MySQLの接続情報をプログラム側に設定したと思うので、再び、DashboardのWeb Appsの画面からReloadをしておきます。

その後で、自分のPythonAnywhereのアプリのURLを開きます。データベースを使うところでも、ちゃんと表示されるのではないでしょうか。

ということで、PythonAnywhereでFlaskアプリを公開できました。

この記事を書いた人

井上 研一

株式会社ビビンコ代表取締役、ITエンジニア/経済産業省推進資格ITコーディネータ。AI・IoTに強いITコーディネータとして活動。2018年、株式会社ビビンコを北九州市に創業。IoTソリューションの開発・導入や、画像認識モデルを活用したアプリの開発などを行っている。近著に「使ってわかった AWSのAI」、「ワトソンで体感する人工知能」。日本全国でセミナー・研修講師としての登壇も多数。