gepuro.net
gepulog

データ分析エンジニアによる備忘録的ブログ

Python3のFlaskをwsgiで動かす

自分の環境ではdocker上で動かしていましたが、本筋には影響を与えないので省略します。

Flaskのドキュメントであるmod_wsgi (Apache)に書いてあるし、Python2の頃は試したことあるから、余裕だろうと油断していた。

sudo apt-get install -y apache2 \
    apache2-mpm-prefork \
    apache2-utils \
    libexpat1 \
    ssl-cert \
    libapache2-mod-wsgi-py3

上のようにインストールした。 また、

/etc/apache2/sites-available/000-default.conf を

<VirtualHost *:80>
ServerName example.com
WSGIDaemonProcess app user=www-data group=www-data
WSGIScriptAlias / /app/app.wsgi
<Directory /app>
WSGIProcessGroup app
WSGIApplicationGRoup %{GLOBAL}
# Order deny,allow
# Allow from all
Require all granted
</Directory>
</VirtualHost>

にします。dockerで動かすだけなので、ファイルを直に編集しています。

ハマりポイント1

libapache2-mod-wsgi-py3をインストールする。

パッケージ名から想像できるが、wsgiはPython3とPython2系で異なる。

ハマりポイント2

apacheの設定では、 Require all grantedを使う。

Python2系では、 Order deny,allow Allow from all で良かった。

http://stackoverflow.com/questions/30642894/getting-flask-to-use-python3-apache-mod-wsgiに救われました。

ちなみにPyttho2系の時は、Flaskでhttpsを使うに書きましたので参考にどうぞ。

Flaskの日本語特のバグ?

@app.route("/hoge/<fuga>", defaults={"page":1})
@app.route("/hoge/<fuga>/", defaults={"page":1})
@app.route("/hoge/<fuga>/<int:page>")

などのようにルーティングを指定した時に、

OK

  • /hoge/日本語
  • /hoge/日本語/
  • /hoge/日本語/2

NG

  • /hoge/日本語/1

となっている。 ルーティングの部分で問題になっているような気がするのだが、もしかしたら他の部分かもしれない。調査が終了したら、報告したいな。

memcachedを導入した

http://flask.pocoo.org/docs/patterns/caching/を参考にして、memcachedをgepulogに導入しました。

from werkzeug.contrib.cache import MemcachedCache
cache = MemcachedCache(['127.0.0.1:11211'])

としておいて、

cache.get("key")
cache.set("key", "value", timeout=5*60)
cache.delete("key")
などのようにして使うことが出来る。

サーバのメモリはまだ余裕があるので、有効活用できるかな?

Flaskでhttpsを使う

認証を使うようなサービスは、SSLを用いてセキュアな通信をしたい。 Flask自身が持ってるwebサーバでは、SSLが使えないので、 apacheやwsgiの力を借りる必要がある。

まず、オレオレ証明書を作る。

$ openssl genrsa -aes128 1024 > server.key
$ openssl req -new -key server.key > server.csr
$ openssl x509 -in server.csr -days 365 -req -signkey server.key > server.crt

とこんな感じで作れる。 作成したものは、それぞれ

  • server.key :秘密鍵
  • server.csr :公開鍵
  • server.crt :デジタル証明書

である。

apacheの設定は、SSLの方は、

LoadModule ssl_module modules/mod_ssl.so
#Listen 443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
SSLPassPhraseDialog builtin
SSLSessionCache     shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

<VirtualHost *:443> ServerName example.com WSGIScriptAlias / /home/hogehoge/apps/hello.wsgi SSLEngine On SSLProtocol all -SSLv2 SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HiGH:+MEDIUM:+LOW SSLCertificateFile /home/hogehoge/apps/server.crt SSLCertificateKeyFile /home/hogehoge/apps/server.key

<Directory /home/hogehoge/apps> WSGIProcessGroup hello WSGIApplicationGRoup %{GLOBAL} WSGIScriptReloading On Order deny,allow Allow from all </Directory>

</VirtualHost>

となる。 通常のhttpの方は、
<VirtualHost *:80>
ServerName example.com
WSGIDaemonProcess hello user=www-data group=www-data
WSGIScriptAlias / /home/hogehoge/apps/hello.wsgi
<Directory /home/hogehoge/apps>
WSGIProcessGroup hello
WSGIApplicationGRoup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
とした。

サービス本体は、 hello.py

#!/usr/bin/python
# -+- coding:utf-8 -*-

from flask import Flask app = Flask(__name__)

@app.route("/") def hello(): return "Hello World!"

if __name__ == "__main__": app.run()

また、hello.wsgiは、
#!/usr/bin/python
# -+- coding:utf-8 -*-
import sys
sys.path.insert(0, '/home/hogehoge/apps')

from hello import app as application

としておく。

これで、https://127.0.0.1/ でアクセス出来るようになった。

参考: