# Flask を HTTPS 化する。
以下3つの起動方法について解説します。
- Flask で対応
- ウェブサーバ(WSGI対応)で対応
- ウェブサーバで対応
なお、この次のページで Heroku で SSL に対応させる方法を紹介します。 Heroku を使う場合は、基本的には、この方法しか使えません。
また CDN, Cloudflare で対応する方法もあります。
# 0. 事前準備
# 1. flask をインストールする。
flask をインストールします。
$ pip install flask
# 2. hello.py を用意します。
なおこのコードは、公式サイトのトップに出てくる 最も簡単なサンプルコードを元にしています (Flask) (opens new window)。
#
# hello.py
#
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run()
# 3. 秘密鍵と証明書を用意します。
SSL 秘密鍵 privkey.pem
と証明書 fullchain.pem
を発行しているものとします。
一昔前は有料でしたが、今は無料で発行できます。
# 4. カレントディレクトリを確認します。
カレントディレクトリは以下のような構成になっているとします。
$ ls -l
fullchain.pem
hello.py
privkey.pem
$
# 1. Flask で対応
Flask で対応させる方法も2種類あります。
# 1.1. app.run()
発行させた秘密鍵と証明書を Flask に対応させる。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == '__main__':
#
# Step 1.
# これを追記します。
#
import ssl
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain(
'fullchain.pem', 'privkey.pem'
)
app.run(ssl_context=ssl_context)
$ #
$ # Step 2. コマンドを実行します。
$ #
$ python hello.py
ここから知りました。ありがとうございます。 こういうのどうやってやり方を見つけるんだろう...
- 【flask】Web サーバーを https 対応する方法 (opens new window)
- How to serve HTTPS *directly* from Flask (no nginx, no apache, no gunicorn) - Flask Snippets (opens new window)
# 1.2. flask run
$ FLASK_APP=hello.py
$ flask run --cert fullchain.pem --key privkey.pem
# 1.3. WSGI ってなに?
WSGI は別に知らなくても大丈夫です。でももし興味がありましたら、以下の動画がとても勉強になります。 WSGI を使って Flask そっくりなウェブアプリケーションを0から作っています。
# 2. ウェブサーバ(WSGI対応)で対応
# 2.1. gunicorn
gunicorn とは WSGI 対応ウェブアプリケーションです。 書式は以下の通りです。
$ pip install gunicorn
$ gunicorn hello:app --certfile fullchain.pem --keyfile privkey.pem
Flask オブジェクトが代入された変数名を指定します。 最初、この意味がわからなくて沈没してました。
$ gunicorn ファイル名:変数名 --certfile fullchain.pem --keyfile privkey.pem
# 2.2. uWSGI
# macOS の場合
uWSGI の方が gunicorn よりも高性能らしいです。 あまり、わかっていません。 普通に pip install すると https が使えません。
$ # 環境変数を設定して...
$ CFLAGS="-I/usr/local/opt/openssl/include"
$ LDFLAGS="-L/usr/local/opt/openssl/lib"
$ UWSGI_PROFILE_OVERRIDE=ssl=true
$
$ # インストール
$ pip install uwsgi -Iv
$
$ # 起動する。
$ uwsgi --https 127.0.0.1:5000,fullchain.pem,privkey.pem --module 'hello:app'
- HTTPS support (from 1.3) - uWSGI (opens new window)
- johnwheeler/install uwsgi with SSL on OS X El Capitan (opens new window)
- uwsgi: unrecognized option '--https' (opens new window)
# Ubuntu の場合
インストールコマンドは以下を参照してください。起動コマンドは同じのはずです。
# 補足
普通に pip install uwsgi
してしまうと --https
オプションが有効になりません。
$ uwsgi --https 127.0.0.1:5000,fullchain.pem,privkey.pem --module 'hello:app'
uwsgi: unrecognized option `--https'
getopt_long() error
$
ただ CFLAGS
, LDFLAGS
が何を指しているかはわかりません。
いつか調べます。
# 2.3. gunicorn と uWSGI の比較
読んではいない...
# 3. ウェブサーバで対応
世の中には Apache と Nginx の二種類の有名なウェブサーバがあります。 最近は Nginx の方が流行りらしいです。この二種類の設定の仕方へのリンクのみ提示いたします。 自分でもやったことがないので、この辺はわかりません。
# 3.1. Apache
Apache は WSGI に対応していません。そのため mod_wsgi というモジュールを追加してあげて WSGI に対応させます。
Web サーバ側(Apache)で、解決する方法もあるみたい...
- PythonのFlaskを初めて触ってから30分で本番環境にデプロイ+ HTTPS通信まで完成 - Qiita (opens new window)
- 意外と簡単!FlaskをHTTPS対応する方法【Let’s encrypt】 (opens new window)
# 3.2. Nginx
Nginx-uWSGI や Nginx-gunicorn がどうやって通信してるかは、 あまりよくわかっていません。
Nginx と uWSGI は uwsgi というプロトコルを使って通信しているらしいです。
uWSGI には --http
, --https
, --socket
というオプションがあります。
この --socket
と --http
, --https
の違いがよくわらない...
Ngnix は、正直言ってなんでこんなに、ガシガシ階層を積み込む感じなのかわからない。 パフォーマンス落ちちゃうんじゃないかな...
- gunicorn + Flask + nginx + Systemdで動かしてみた - Qiita (opens new window)
- Flask + uWSGI + Nginx でハローワールドするまで - Qiita (opens new window)
でも Nginx の方が流行りらしい... Apache よりは Ngnix の方がシェアがでかくなったらしい。 ちゃんと読まんとな...
# どこで HTTPS 化する?
色々な構成があるので、どこで HTTPS 化するのか疑問だったのですが、 安全なところまでは HTTP 通信を使っていいのかなと感じたりしています。
何を持って安全とするかは、よくわからないのですが。
基本的に HTTPS 通信は重いらしいです。 そのため不要であれば、サーバ間で HTTPS 通信は避けたい様な気もします。
# Flask が持っているサーバ
Flask は開発用のサーバを自分の中に持っています。app.run()
や flask run
で起動できます。
公式ドキュメントはこちらから。
Flask は werkzeug というライブラリをメインに使って開発されています。 その werkzeug の中に run_simple という試験用のウェブサーバの関数があります。 これを動かしている気配があります。
ちなみに werkzeug の run_simple は Python の標準ライブラリである http.client (opens new window) から作っているようです。
# app.run() と flask run の違い
app.run()
した時と flask run
した時で、そんなに大きな違いはなさそうです。
ただ、若干挙動に違いがあります。
どう動きが変わってくるかと言うとは、パスが変わりす。
app.run()
した時は「スクリプト」として実行されます。
flask run
した時は「ライブラリ」として import された上で実行されます。
いつハマるかというと、もともと1つだったファイルを、複数に分割して使おうとすると import で盛大にハマります。
もし後々ファイルを分割することを検討している場合は、
flask run
で起動して app.run()
では起動しないことを、オススメしたいです。
ただ、import を書き換えれば、問題は解決するので、大した話ではないのですが。 色々調べた挙句 2, 3 万文字の記事になりました...
説明が悪くて伝わりづらいのですが、なんとなくの雰囲気だけ伝わればと思いました。
# おわりに
ここまで以下のように見てきました。
以上になります。ありがとうございました。