Flask の app.run() を本番環境で使ってはいけない理由

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高機能だが設定が複雑
WaitressWindows でも動作する純 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 $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Flask の警告メッセージ

Flask 自身も app.run() を本番で使わないよう警告を出している。

WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.

この警告は無視せず、必ず本番用の WSGI サーバーを使用すること。