- Gunicornの設定が難しすぎる…
- 動かすコマンドは?
- 実践的な設定方法を教えて!
このような方に向けて書きました。
中小規模のDjangoアプリのデプロイによく使われるアプリケーションサーバーがGunicornです。
ところが、初めての設定・起動は少し戸惑うことも多いはず。
本記事では以下のような内容を解説します。
- ワーカー数の設定
- Nginxとの連携
- UNIXソケットとTCPの使い分け
- Systemdを使った自動化の手順
本記事を読み終わる頃には、Gunicornの苦手意識がだいぶ薄らいでいるはずです。
ぜひ、手を動かしながら身につけていきましょう。
Gunicornの基本的な動かし方
まずはGunicornを動かすための基本から押さえていきましょう。
実践でよく使われるSystemdへの登録でも必要な知識になりますので、ぜひ理解していきましょう。
Gunicornのインストール
一般的なPythonパッケージと同様、pipやpoetryでインストールができます。
# pipの場合
pip install gunicorn
# poetryの場合
poetry add gunicorn
できればローカルでの開発中にインストールを済ませておきましょう。
Gunicornを立ち上げる(簡易版)
簡単にGunicornを立ち上げたい場合には、次のコマンドを実行します。
gunicorn --workers 7 プロジェクト名.wsgi:application
このコマンドは開発環境や簡単なテストで使われるものです。
本番環境ではSystemdを使って自動制御する方法がよく使われるので、記事の後半で解説します。
ここでgunicorn
コマンドに渡している2つの引数を解説します。
Gunicornワーカー
--workers 7
とすることで、7つのプロセスを起動しています。
Gunicornの公式ドキュメント によると、ワーカー数の計算方法は以下の通りです。
(CPUコア数 × 2) + 1
たとえば契約したサーバーのCPUコア数が3なら、ワーカー数は7となります。
ちなみにLinuxの場合には、次のコマンドでCPUコア数を調べられます。
nproc
とはいえこの数値は目安に過ぎないので、実際の稼働状況を見ながら調整する必要はあります。
WSGIアプリケーション
プロジェクト名.wsgi:application
には、Gunicornが起動したら最初に読み込むエントリーポイントを指定します。
たとえば以下のようなDjangoプロジェクトなら、core.wsgi:application
です。
.
├── core
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
├── manage.py
├── poetry.lock
└── pyproject.toml
デプロイ時のDjangoアプリのエントリーポインはwsgi.py
なので、このような設定になるわけです。
より実践的なGunicornの使い方
gunicorn
コマンドを実行した場合、次のケースではGunicornを手動で再起動する必要があります。
- サーバーを再起動した場合
- Gunicornプロセスが停止した場合
サーバーは起動し続ける必要があるため、手動での再起動は現実的ではないです。
本番環境では、サービスを安定稼働させるために、SystemdでGunicornを自動管理(再起動・停止・監視)させます。
GunicornをSystemdサービスに設定
Gunicornサービスファイルを作成します。
sudo vi /etc/systemd/system/gunicorn.service
viエディタが開くので、以下の内容を追記してください。
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/your/project
ExecStart=仮想環境へのパス/bin/gunicorn --workers 7 --bind 127.0.0.1:8000 プロジェクト名.wsgi:application
[Install]
WantedBy=multi-user.target
ここで書き換えるべきは、ハイライトした箇所です。
WorkingDirectory
WorkingDirectory
には、Djangoプロジェクトまでのパスを指定します。
パスの調べ方は、manage.py
があるディレクトリまで降りてからpwd
コマンドを実行してください。
cd /path/to/your_project_root
pwd
ここで返ってきたパスをWorkingDirectory
に指定してあげればOKです。
ExecStart
ExecStart
はGunicornを立ち上げるコマンドを書く場所です。
まずExecStart=
の後に書くパスは「Gunicornの実行ファイルがあるパス」を指定し、次のコマンドで知ることができます。
which gunicorn
--worker
の後の数字は、すでに説明したとおりサーバーのCPUコア数から求められます。
(CPUコア数 × 2) + 1
プロジェクト名.wsgi:application
の部分もすでにご紹介したとおりですね。
Gunicornが最初に読み込むエントリーポイントを指定することになります。
--bind
については、UNIXソケットを使う方法とTCPを使う方法があるので、後ほど詳しく解説します。
サービスをリロードして有効化
Gunicornサービスを有効化するため、サービスをリロードします。
# サービスファイルの変更をsystemdに認識させる
sudo systemctl daemon-reload
# Gunicornサービスを起動
sudo systemctl start gunicorn
# サーバー再起動時にGunicornサービスが自動的に起動するよう設定
sudo systemctl enable gunicorn
これでGunicornが自動管理されるようになりました。
UNIXソケットを使う方法とTCPを使う方法
Systemdサービスの設定ファイルに--bind
を指定しました。
ここではこの項目に設定するUNIXソケットとTCPに関する設定方法をお伝えします。
TCPとUNIXソケットの使い分け
端的に、次の基準で使い分けると良いです。
- TCP
- NginxとGunicornが別サーバーにある
- または別コンテナにある
- UNIXソケット
- NginxとGunicornが同じサーバーにある
基本的にはUNIXソケットの方がパフォーマンスやセキュリティ面で有利なので、優先して使うべきです。
どうしてもUNIXソケットが使えない場合には、TCPを選択するイメージで良いかと思います。
UNIXソケットの設定方法
UNIXソケットは、ファイルで通信する方法です。
--bind
にはUNIXソケットファイルパスを指定します。
gunicorn --workers 7 --bind http://unix:/run/sock/my_project.sock プロジェクト名.wsgi:application
/run/my_project.sock
はソケットファイルの絶対パスです。
NginxとGunicornは、このファイルを中継してやりとりをします。
Nginxの設定ファイルでは、proxy_pass
にUNIXソケットを指定します。
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://unix:/run/sock/my_project.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
上記の設定では/run/sock
ディレクトリ内のソケットファイルをwww-data
ユーザーが読み込み・編集を行います。
そのため、/run/sock
ディレクトリを作成してwww-data
に権限を付与しておきましょう。
sudo mkdir /run/sock/
sudo chown www-data:www-data /run/sock/
sudo chmod 750 /run/sock/
この設定では、80番ポートに飛んできたリクエストをUNIXソケット経由でGunicornに転送しています。
TCPバインドの設定方法
Gunicorn がリクエストをHTTPで受け取る場合にTCPバインドを使います。
- Nginx と Gunicorn が別のサーバーにある
- GunicornをHTTPサーバーとして公開する
こんな時にはUNIXソケットが使えないので、消去法的にTCPバインドを使うことになります。
gunicorn --workers 7 --bind 0.0.0.0:8000 プロジェクト名.wsgi:application
上記の例では、IPアドレスとして0.0.0.0
を指定しました。これは、すべてのインターフェースでリクエストを受け付けるという意味です。
また8000
は、Gunicornで標準的なポート番号です。
Ningxの設定ファイル例は以下のとおりです。
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
proxy_pass
で Gunicorn がバインドされたアドレスとポートに転送します。
この設定では、クライアントからのリクエストをNginxが受け取り、127.0.0.1:8000
で待ち受けているGunicornに転送します。
まとめ
本記事では、Gunicornの基本から実践的なSystemdへの登録方法まで解説しました。
最初は戸惑うかもしれませんが、ワーカー数の設定やNginxとの連携、Systemdを使った自動化の設定など、一度理解してしまえばそこまで複雑なツールではありません。
Gunicornを正しく設定できると、Djangoアプリケーションを安定して本番稼働できるようになるのでマスターしていきましょう。
特にUNIXソケットは、パフォーマンス・セキュリティを両立できるので必須項目です。
ぜひ、手を動かしてGunicornを身につけていってください。
コメント