1. はじめに
- 業務で「システム内のGunicornに課題がある」という相談があったが、自分としては「そもそもGunicornって何??」という状態だったため、そもそも何なのか、どのように使うものなのかを簡単に確認する。
2. Gunicornとは(自分の理解)
- Gunicornとは何か?
- PythonでWebアプリを開発する際のフレームワークとしてDjangoやFlaskがあるが、Gunicornはその前段に配置して、WSGIサーバ(WebアクセスをPythonアプリにつなぐ役割)として動作するもの。
- FlaskだけでもWebサーバが作れるがそれではダメなのか?
- Flaskにも開発用サーバ機能がついているが、シングルスレッドであり開発環境向け。Gunicornは複数ワーカーで並列処理ができるなど本番環境向けの対応が可能。
- 本番環境ではどのような構成になるのか?
- Nginx(静的資材処理など) - Gunicorn(WSGIサーバ) - Flask(Pythonアプリ) のような構成になる。
3. やったこと
- EC2インスタンス(Amazon Linux 2023)に、GunicornとFlaskをインストールする。
- 簡単な初期設定を行い、httpリクエストがGunicornとFlaskでどのように処理されるのかを確認する。
4. 構成図
5. 手順
5.1 GunicornとFlaskのインストール
- GunicornとFlaskをインストールする。
[ec2-user@ip-10-0-0-220 ~]$ sudo dnf install -y python3-pip
[ec2-user@ip-10-0-0-220 ~]$ python3 -m venv venv
[ec2-user@ip-10-0-0-220 ~]$ source venv/bin/activate
(venv) [ec2-user@ip-10-0-0-220 ~]$
(venv) [ec2-user@ip-10-0-0-220 ~]$ pip install flask==3.0.0
(venv) [ec2-user@ip-10-0-0-220 ~]$ pip install gunicorn==21.2.0
5.2 Gunicornの初期設定
- Gunicornの設定ファイルを作成する。
gunicorn_config.py
"""
Gunicorn configuration file
"""
import multiprocessing
# Server socket
bind = "0.0.0.0:8000"
backlog = 2048
# Worker processes
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync"
worker_connections = 1000
timeout = 30
keepalive = 2
# Logging
accesslog = "-" # 標準出力にアクセスログを出力
errorlog = "-" # 標準エラー出力にエラーログを出力
loglevel = "info"
access_log_format = '%(t)s [Worker:%(p)s] %(h)s "%(r)s" %(s)s %(b)s %(M)sms'
- CPU数x2個のワーカーが推奨?とのことで、今回のEC2インスタンスは2CPUのためワーカー数5個となる。
- アクセスログは時刻、処理を担当したワーカー、クライアントIP、HTTPメソッド/パス、ステータスコード、レスポンスサイズ、処理時間を取得する。
5.3 Flaskのサンプルアプリ
- Flaskのサンプルアプリを作製する。(パスなしでアクセスされた場合、GunicornワーカーのプロセスIDをJSONで返す)
app.py
"""
Simple Flask application for Gunicorn demo
"""
from flask import Flask, jsonify
import os
app = Flask(__name__)
@app.route('/')
def index():
return jsonify({
'message': 'Hello from Gunicorn!',
'status': 'running',
'worker_id': os.getpid()
})
@app.route('/health')
def health():
return jsonify({'status': 'healthy'}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
5.4 動作確認
Gunicornの起動
- Gunicornを設定ファイル、およびFlaskアプリのファイルを指定して起動する。
- 設定どおり、ワーカーが5つ起動される。
(venv) [ec2-user@ip-10-0-0-220 ~]$ gunicorn -c gunicorn_config.py --access-logfile - app:app
[2025-11-10 06:36:23 +0000] [3784] [INFO] Starting gunicorn 21.2.0
[2025-11-10 06:36:23 +0000] [3784] [INFO] Listening at: http://0.0.0.0:8000 (3784)
[2025-11-10 06:36:23 +0000] [3784] [INFO] Using worker: sync
[2025-11-10 06:36:23 +0000] [3785] [INFO] Booting worker with pid: 3785
[2025-11-10 06:36:23 +0000] [3786] [INFO] Booting worker with pid: 3786
[2025-11-10 06:36:23 +0000] [3787] [INFO] Booting worker with pid: 3787
[2025-11-10 06:36:24 +0000] [3788] [INFO] Booting worker with pid: 3788
[2025-11-10 06:36:24 +0000] [3789] [INFO] Booting worker with pid: 3789
curlアクセスの処理
- インターネット上のクライアントからcurlアクセスする。
- 何回かアクセスすると、複数のワーカーで処理されていることが分かる。
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3787}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3785}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3785}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3785}
mypc:/mnt/c/Users/mksamba$ curl http://y.y.y.y:8000
{"message":"Hello from Gunicorn!","status":"running","worker_id":3786}
アクセスログ
- 今回はアクセスログを標準出力しており、以下のように出力される。
[10/Nov/2025:06:36:58 +0000] [Worker:<3787>] x.x.x.x "GET / HTTP/1.1" 200 71 2ms
[10/Nov/2025:06:36:59 +0000] [Worker:<3785>] x.x.x.x "GET / HTTP/1.1" 200 71 2ms
[10/Nov/2025:06:37:00 +0000] [Worker:<3785>] x.x.x.x "GET / HTTP/1.1" 200 71 0ms
[10/Nov/2025:06:37:01 +0000] [Worker:<3785>] x.x.x.x "GET / HTTP/1.1" 200 71 0ms
[10/Nov/2025:06:37:02 +0000] [Worker:<3786>] x.x.x.x "GET / HTTP/1.1" 200 71 2ms
[10/Nov/2025:06:37:03 +0000] [Worker:<3786>] x.x.x.x "GET / HTTP/1.1" 200 71 0ms
プロセス障害対応
- 今回はワーカー数を5個に設定している。
- ワーカーがプロセスID 4669~4673 で動作している状態で、4671をkillしてもすぐに別のワーカー(5538)が自動的に起動された。
[ec2-user@ip-10-0-0-220 ~]$ ps aux | grep gunicorn
ec2-user 3784 0.0 2.4 245352 22248 ? S 06:36 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4669 0.0 2.8 254012 26528 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4670 0.0 2.8 254016 26532 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4671 0.0 2.8 254016 26532 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4672 0.0 2.8 254016 26464 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4673 0.0 2.8 254016 26504 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 5537 0.0 0.2 222328 2108 pts/2 S+ 06:59 0:00 grep --color=auto gunicorn
[ec2-user@ip-10-0-0-220 ~]$ kill 4671
[ec2-user@ip-10-0-0-220 ~]$ ps aux | grep gunicorn
ec2-user 3784 0.0 2.4 245352 22248 ? S 06:36 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4669 0.0 2.8 254012 26528 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4670 0.0 2.8 254016 26532 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4672 0.0 2.8 254016 26464 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 4673 0.0 2.8 254016 26504 ? S 06:54 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 5538 2.6 2.8 254016 26528 ? S 06:59 0:00 /home/ec2-user/venv/bin/python3 /home/ec2-user/venv/bin/gunicorn -c gunicorn_config.py --access-logfile - app:app
ec2-user 5593 0.0 0.2 222328 2116 pts/2 S+ 06:59 0:00 grep --color=auto gunicorn
6. 所感
- 「Gunicornって何?」という状態からは脱出できたが、実際の環境でどのように設定すべきかなど学習していきたい。
- 今回もAWS社のコーディングツール「Kiro」のVibeモードを使って、「Gunicornのデモ環境を作って」「ログが出ないんだけど」「Flaskだけの場合と比較してどのようなメリットがあるの?」などのやりとりをして助けてもらった。Vibeモードでちょっとした(理解できる範囲の)コードを作ってもらう分には、便利に使いこなせている気がする。
