\ お問い合わせはこちら! /

GunicornでDjangoプロジェクトをデプロイする方法【Nginx使用】

  • 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を身につけていってください。

この記事が気に入ったら
フォローしてね!

シェア・記事の保存はこちら!

この記事を書いた人

karo@プログラマのアバター karo@プログラマ プログラマ

「書くことで人の役にたつ」をモットーに活動中。
本職はプログラマで、Pythonが得意。
基本情報技術者試験合格。

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)