Flaskで作ったサービスをさくらのWebサーバーで公開

紹介しているサイトは多いので今更になるのですが、さくらのWebサーバーでFlaskで作ったサービスをCGIとして動かすことが出来ます。

このブログでは何度も登場しているのでちょっとしつこいですが、さくらのWebサーバーは比較的安価で自由度が高いため、負荷の低いWebサービスならさくらのWebサーバーで稼働させることは選択肢として十分にあると思います。

まずはさくらのWebサーバーにSSHログインしてpyenvを入れ、その後pipでflaskなどの各種モジュールを入れていく必要がありますが。それは下記のサイトで説明されているので、ここでは割愛します。

dayjournal | Try #019 – さくらのレンタルサーバでFlaskを利用した住所検索APIを構築してみた

その設定後、作った Flaskアプリの本体である app.py の他に、index.cgi、.htaccess をアップロードすれば良いのですが、初めて動かした時自分はそれらのファイルの意味をよくわかっていなかったので、あらためてここで説明します。

index.cgi

#!/home/xxx/.pyenv/versions/flask_peewee_3.6.9/bin/python

# pythonのパスです。xxxの部分を自分のIDに変えましょう

import cgitb
cgitb.enable()

from wsgiref.handlers import CGIHandler
from app import app
from sys import path

path.insert(0, '/home/xxx/www/cgi/') # cgiを設置しているディレクトリです
from app import app
class ProxyFix(object):
  def __init__(self, app):
      self.app = app
  def __call__(self, environ, start_response):
      environ['SERVER_NAME'] = "sample.com" # ドメインです
      environ['SERVER_PORT'] = "80"
      environ['SERVER_PROTOCOL'] = "HTTP/1.1"
      return self.app(environ, start_response)
if __name__ == '__main__':
   app.wsgi_app = ProxyFix(app.wsgi_app)
   CGIHandler().run(app)

このindex.cgiがCGIとして動いて、リクエストを受け取ります。

http://sample.com/index.cgi/hoge みたいなアクセスがあったとすると、app.py に対して「/hogeというアクセスがあったよ」、と引き渡すことで、CGIとしてのレスポンスを返させます。

app.pyはモジュールとしてimportしているだけなので、実行権は不要です。index.cgi にだけ実行権を付与しておけば、CGIとして動きます。

app.py以外にもファイルがたくさんある場合も同様です。ルーティングを行う本体のファイルがapp.pyであればよいです。

ちょっとうろ覚えですが、ProxyFixの部分は独自ドメインを使わないなら設定しなくてよかった気がします。

.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.cgi/$1 [QSA,L]
<Files ~ "\.py$">
  deny from all
</Files>

この設定で、たとえば http://sample.com/hogehoge というようなアクセスを、http://sample.com/index.cgi/hogehoge というアクセスに変えることが出来ます。

こうすることで、必ずindex.cgi を経由してくれるようになります。

また、.py ファイルへのアクセスを禁止していますが、よくある構成では.envとか.yamlみたいな設定ファイルを置くこともあるでしょう。それらへのアクセス権も deny from allしておくとよいです。

先程述べたように、.pyファイルは直接実行しているわけじゃないので、deny from allしても動きますし、しないとソースコードを盗まれる可能性があり危険です。

うまく動かない場合、さくらのWebサーバーのダッシュボードの「サーバーステータス」→「エラーログ」からエラーログを見ることができるのでヒントになります。

これを最後にやったのは数年前なので細かいことはちょっと忘れてしまいましたが、何かの役に立つかもしれないので、念のため残しておきます。