Flask の app.run() は開発用サーバーを起動するメソッドであり、本番環境で使ってはいけない。その理由と正しい本番デプロイ方法を解説する。
app.run() の問題点
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000) # 本番で使ってはいけない
Flask の組み込みサーバー(Werkzeug の開発サーバー)には以下の問題がある。
| シングルスレッド | デフォルトでは同時に1リクエストしか処理できない |
| パフォーマンス | 最適化されておらず、大量のリクエストを捌けない |
| セキュリティ | 本番向けのセキュリティ対策が施されていない |
| 安定性 | 長時間稼働やエラー時の復旧機構がない |
debug=True の危険性
本番で debug=True を設定すると、さらに深刻な問題が発生する。
app.run(debug=True) # 絶対に本番で使わない
デバッグモードでは Werkzeug のインタラクティブデバッガが有効になり、エラー画面から任意の Python コードを実行できてしまう。攻撃者にサーバーを完全に乗っ取られる可能性がある。
threaded=True でも不十分
app.run(threaded=True) # マルチスレッドにしても本番には不十分
threaded=True で複数リクエストを並行処理できるようになるが、それでも本番環境の要件を満たさない。ワーカー管理、ログ、監視、graceful restart などの機能がない。
正しい本番デプロイ
WSGI サーバーを使う。代表的な選択肢は以下のとおり。
| Gunicorn | 最も一般的。シンプルで使いやすい |
| uWSGI | 高機能だが設定が複雑 |
| Waitress | Windows でも動作する純 Python 実装 |
pip install gunicorn gunicorn -w 4 -b 0.0.0.0:8000 app:app
さらに Nginx をリバースプロキシとして前段に配置するのが一般的である。
server { listen 80; server_name example.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host remote_addr; } }
Flask の警告メッセージ
Flask 自身も app.run() を本番で使わないよう警告を出している。
この警告は無視せず、必ず本番用の WSGI サーバーを使用すること。