Ubuntu20.04でPostgres、Nginx、Uvicornを使用してASGIDjangoアプリをセットアップする方法
序章
Django は、PythonアプリケーションまたはWebサイトを立ち上げるのに役立つ強力なWebフレームワークです。 Djangoには、コードをローカルでテストするための簡略化された開発サーバーが含まれていますが、本番環境に関連するものには、より安全で強力なWebサーバーが必要です。
Djangoアプリをデプロイする従来の方法は、Webサーバーゲートウェイインターフェイス(WSGI)を使用することです。 ただし、Python 3の出現と非同期実行のサポートにより、非同期サーバーゲートウェイインターフェース(ASGI)を使用して非同期呼び出し可能ファイルを介してPythonアプリを実行できるようになりました。 WSGIの後継であるPythonのASGI仕様は、WSGIのスーパーセットであり、WSGIのドロップイン置換になります。
Djangoでは、コードを内部で同期できる「非同期外部、同期内部」モードが可能ですが、ASGIサーバーはリクエストを非同期で処理します。 Webサーバーに非同期呼び出し可能を許可することにより、アプリケーションごとに複数の着信イベントと発信イベントを処理できます。 Djangoアプリケーションは、下位互換性を可能にし、並列コンピューティングの複雑さを回避するために、内部で同期されています。 これは、DjangoアプリがWSGIからASGIに切り替えるために変更を必要としないことも意味します。
このガイドでは、Djangoアプリケーションをサポートおよび提供するために、Ubuntu20.04にいくつかのコンポーネントをインストールして構成します。 デフォルトのSQLiteデータベースを使用する代わりに、PostgreSQLデータベースをセットアップします。 ASGI実装であるUvicornとペアになっているGunicornアプリケーションサーバーを構成して、アプリケーションと非同期でインターフェイスします。 次に、GunicornにリバースプロキシするようにNginxを設定し、アプリを提供するためのセキュリティ機能とパフォーマンス機能にアクセスできるようにします。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Ubuntu 20.04の初期サーバーセットアップガイドに従ってセットアップされた1つのUbuntu20.04サーバー。これには、
sudo権限を持つ非rootユーザーが含まれます。
ステップ1—Ubuntuリポジトリからパッケージをインストールする
プロセスを開始するには、Ubuntuリポジトリから必要なすべてのアイテムをダウンロードしてインストールします。 Pythonパッケージマネージャーpipを使用して、少し後で追加のコンポーネントをインストールします。
まず、ローカルのaptパッケージインデックスを更新してから、パッケージをダウンロードしてインストールする必要があります。 インストールするパッケージは、プロジェクトで使用するPythonのバージョンによって異なります。
次のコマンドを使用して、必要なシステムパッケージをインストールします。
sudo apt update sudo apt install python3-venv libpq-dev postgresql postgresql-contrib nginx curl
このコマンドは、仮想環境をセットアップするためのPythonライブラリ、Postgresデータベースシステムとそれと対話するために必要なライブラリ、およびNginxWebサーバーをインストールします。 次に、Djangoアプリケーション用のPostgreSQLデータベースとユーザーを作成します。
ステップ2—PostgreSQLデータベースとユーザーを作成する
このステップでは、Djangoアプリケーション用のデータベースとデータベースユーザーを作成します。
デフォルトでは、Postgresはローカル接続に「ピア認証」と呼ばれる認証スキームを使用します。 これは、ユーザーのオペレーティングシステムのユーザー名が有効なPostgresユーザー名と一致する場合、そのユーザーはそれ以上の認証なしでログインできることを意味します。
Postgresのインストール中に、postgresという名前のオペレーティングシステムユーザーが、postgresPostgreSQL管理ユーザーに対応するように作成されました。 管理タスクを実行するには、このユーザーを使用する必要があります。 -uオプションを使用すると、sudoを使用してユーザー名を渡すことができます。
次のように入力して、インタラクティブなPostgresセッションにログインします。
sudo -u postgres psql
要件を設定できるPostgreSQLプロンプトが表示されます。
まず、プロジェクトのデータベースを作成します。
CREATE DATABASE myproject;
注:すべてのPostgresステートメントはセミコロンで終了する必要があります。 問題が発生している場合は、コマンドがセミコロンで終わっていることを確認してください。
次に、プロジェクトのデータベースユーザーを作成します。 安全なパスワードを選択してください。
CREATE USER myprojectuser WITH PASSWORD 'password';
その後、作成したユーザーの接続パラメーターのいくつかを変更します。 これにより、データベース操作が高速化されるため、接続が確立されるたびに正しい値を照会して設定する必要がなくなります。
デフォルトのエンコーディングをUTF-8に設定します。これは、Djangoが期待するものです。 また、デフォルトのトランザクション分離スキームを「読み取りコミット」に設定します。これにより、コミットされていないトランザクションからの読み取りがブロックされます。 最後に、タイムゾーンを設定します。 デフォルトでは、DjangoプロジェクトはUTCを使用するように設定されます。 これらはすべて、Djangoプロジェクト自体からの推奨事項です。
ALTER ROLE myprojectuser SET client_encoding TO 'utf8'; ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed'; ALTER ROLE myprojectuser SET timezone TO 'UTC';
これで、新しいユーザーに新しいデータベースを管理するためのアクセス権を与えることができます。
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
終了したら、次のように入力してPostgreSQLプロンプトを終了します。
\q
これで、Djangoがデータベース情報に接続して管理できるようにPostgresが設定されました。
ステップ3—プロジェクト用のPython仮想環境を作成する
データベースができたので、残りのプロジェクト要件の準備を始めることができます。 管理を容易にするために、Python要件を仮想環境内にインストールします。
まず、プロジェクトファイルを保持できるディレクトリを作成して移動します。
mkdir ~/myprojectdir cd ~/myprojectdir
次に、Pythonの組み込み仮想環境ツールを使用して、新しい仮想環境を作成します。
python3 -m venv myprojectenv
これにより、myprojectdirディレクトリ内にmyprojectenvというディレクトリが作成されます。 内部には、Pythonのローカルバージョンとpipのローカルバージョンがインストールされます。 これを使用して、プロジェクト用に分離されたPython環境をインストールおよび構成できます。
プロジェクトのPython要件をインストールする前に、仮想環境をアクティブ化する必要があります。 次のように入力すると、次のように入力できます。
source myprojectenv/bin/activate
プロンプトが変化して、Python仮想環境内で操作していることを示します。 (myprojectenv)user@host:~/myprojectdir$のようになります。
Djangoを仮想環境にインストールします。 プロジェクトに固有の環境にDjangoをインストールすると、プロジェクトとその要件を個別に処理できるようになります。 仮想環境をアクティブにして、Django、Gunicorn、Uvicorn、およびpsycopg2PostgreSQLアダプターをpipのローカルインスタンスとともにインストールします。
注:仮想環境がアクティブ化されている場合(プロンプトの前に(myprojectenv)がある場合)、使用している場合でも、pip3の代わりにpipを使用してくださいPython3。 仮想環境のツールのコピーには、Pythonのバージョンに関係なく、常にpipという名前が付けられます。
pip install django gunicorn uvicorn psycopg2-binary
これで、Djangoプロジェクトを開始するために必要なすべてのソフトウェアが揃いました。
ステップ4—新しいDjangoプロジェクトの作成と構成
Pythonコンポーネントをインストールすると、実際のDjangoプロジェクトファイルを作成できます。
Djangoプロジェクトの作成
すでにプロジェクトディレクトリがあるので、ここでファイルをインストールするようにDjangoに指示できます。 通常の実際のコードを使用して第2レベルのディレクトリを作成し、このディレクトリに管理スクリプトを配置します。 これの鍵は、Djangoが現在のディレクトリに関連する決定を行うことを許可するのではなく、ディレクトリを明示的に定義していることです。
django-admin startproject myproject ~/myprojectdir
この時点で、プロジェクトディレクトリ(このチュートリアルでは~/myprojectdir)には次の内容が含まれているはずです。
~/myprojectdir/manage.py:Djangoプロジェクト管理スクリプト。~/myprojectdir/myproject/:Djangoプロジェクトパッケージ。 これには、__init__.py、asgi.py,settings.py、urls.py、およびwsgi.pyファイルが含まれている必要があります。~/myprojectdir/myprojectenv/:前に作成した仮想環境ディレクトリ。
プロジェクト設定の調整
プロジェクトファイルを作成したら、いくつかの設定を調整する必要があります。 テキストエディタで設定ファイルを開きます。
nano ~/myprojectdir/myproject/settings.py
ALLOWED_HOSTSディレクティブを見つけることから始めます。 これは、Djangoインスタンスへの接続に使用できるサーバーのアドレスまたはドメイン名のリストを定義します。 このリストにないHostヘッダーを持つ着信要求は、例外を発生させます。 Djangoでは、特定のクラスのセキュリティの脆弱性を防ぐためにこれを設定する必要があります。
角かっこ内に、Djangoサーバーに関連付けられているIPアドレスまたはドメイン名をリストします。 エントリをコンマで区切って、各項目を引用符で囲んでリストします。 ドメイン全体とサブドメインを許可するには、エントリの先頭にピリオドを追加します。 以下のスニペットには、これを行う方法を示すために使用されるコメントアウトされた例がいくつかあります。
注:ローカルのNginxインスタンスを介して接続をプロキシするため、オプションの1つとしてlocalhostを必ず含めてください。
〜/ myprojectdir / myproject / settings.py
. . . # The simplest case: just add the domain name(s) and IP addresses of your Django server # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5'] # To respond to 'example.com' and any subdomains, start the domain with a dot # ALLOWED_HOSTS = ['.example.com', '203.0.113.5'] ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
次に、データベースアクセスを構成するセクションを見つけます。 DATABASESで始まります。 ファイル内の構成はSQLiteデータベース用です。 プロジェクト用のPostgreSQLデータベースはすでに作成されているため、設定を調整する必要があります。
PostgreSQLデータベース情報で設定を変更します。 pipでインストールしたpsycopg2アダプターを使用するようにDjangoに指示します。 データベース名、データベースユーザー名、データベースユーザーのパスワードを指定してから、データベースがローカルコンピューター上にあることを指定する必要があります。 PORT設定は空の文字列のままにしておくことができます。
〜/ myprojectdir / myproject / settings.py
. . .
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
. . .
次に、ファイルの一番下に移動し、静的ファイルを配置する場所を示す設定を追加します。 これは、Nginxがこれらのアイテムのリクエストを処理できるようにするために必要です。 次の行は、ベースプロジェクトディレクトリのstaticというディレクトリにそれらを配置するようにDjangoに指示しています。
〜/ myprojectdir / myproject / settings.py
. . . STATIC_URL = '/static/' import os STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
終了したら、ファイルを保存して閉じます。
プロジェクトの初期設定の完了
これで、管理スクリプトを使用して、初期データベーススキーマをPostgreSQLデータベースに移行できます。
~/myprojectdir/manage.py makemigrations ~/myprojectdir/manage.py migrate
次のように入力して、プロジェクトの管理ユーザーを作成します。
~/myprojectdir/manage.py createsuperuser
ユーザー名を選択し、メールアドレスを入力し、パスワードを選択して確認する必要があります。
次のように入力して、構成したディレクトリの場所にすべての静的コンテンツを収集できます。
~/myprojectdir/manage.py collectstatic
操作を確認する必要があります。 静的ファイルは、プロジェクトディレクトリ内のstaticというディレクトリに配置されます。
サーバーの初期設定ガイドに従った場合は、サーバーを保護するUFWファイアウォールが必要です。 開発サーバーをテストするには、使用するポートへのアクセスを許可する必要があります。
次のように入力して、ポート8000の例外を作成します。
sudo ufw allow 8000
最後に、次のコマンドを使用してDjango開発サーバーを起動することにより、プロジェクトをテストできます。
~/myprojectdir/manage.py runserver 0.0.0.0:8000
Webブラウザーで、サーバーのドメイン名またはIPアドレスにアクセスし、その後に:8000を続けます。
http://server_domain_or_IP:8000
デフォルトのDjangoインデックスページが表示されます。
アドレスバーのURLの末尾に/adminを追加すると、createsuperuserコマンドで作成した管理用ユーザー名とパスワードの入力を求められます。
認証後、デフォルトのDjango管理インターフェースにアクセスできます。
探索が終了したら、ターミナルウィンドウでCTRL+Cを押して、開発サーバーをシャットダウンします。
プロジェクトにサービスを提供するGunicornの能力をテストする
このチュートリアルでは、GunicornをUvicornと組み合わせて使用して、アプリケーションをデプロイします。 Gunicornは伝統的にWSGIアプリケーションの展開に使用されますが、ASGI展開を提供するためのプラグ可能なインターフェイスも提供します。 これは、ASGIサーバー(uvicorn)によって公開されているワーカークラスを使用できるようにすることで実現されます。 Gunicornはより成熟した製品であり、Uvicornよりも多くの構成を提供するため、Uvicornのメンテナは、gunicornとuvicornワーカークラスをフル機能のサーバーおよびプロセスマネージャーとして使用することをお勧めします。
仮想環境を離れる前に、Gunicornをテストして、アプリケーションに対応できることを確認します。
uvicornワーカーをgunicornサーバーで使用するには、プロジェクトディレクトリに入り、次のgunicornコマンドを使用してプロジェクトのASGIモジュールをロードします。
cd ~/myprojectdir gunicorn --bind 0.0.0.0:8000 myproject.asgi -w 4 -k uvicorn.workers.UvicornWorker
これにより、Django開発サーバーが実行されていたのと同じインターフェースでGunicornが起動します。 戻ってアプリをもう一度テストできます。
注:ASGIアプリケーションを実行するためにGunicornを使用する必要はありません。 uvicornのみを使用するには、次のコマンドを使用します。
uvicorn myproject.asgi:application --host 0.0.0.0 --port 8080
注: Gunicornはこれに関与する静的CSSコンテンツを見つける方法を知らないため、管理インターフェースにはスタイルが適用されません。
これらのコマンドを開始した後もDjangoウェルカムページが表示される場合は、gunicornがページを提供し、意図したとおりに機能していることを確認しています。 gunicornコマンドを使用して、Pythonのモジュール構文を使用して、アプリケーションへのエントリポイントであるDjangoのasgi.pyファイルへの相対ディレクトリパスを指定して、Gunicornにモジュールを渡しました。 このファイルの中には、applicationという関数が定義されており、アプリケーションとの通信に使用されます。 ASGI仕様の詳細については、公式ASGIWebサイトにアクセスしてください。
テストが終了したら、ターミナルウィンドウでCTRL+Cを押してGunicornを停止します。
これで、Djangoアプリケーションの構成が完了しました。 次のように入力すると、仮想環境から戻ることができます。
deactivate
プロンプトの仮想環境インジケーターが削除されます。
ステップ5—Gunicorn用のsystemdソケットおよびサービスファイルの作成
前のセクションでは、GunicornがDjangoアプリケーションと対話できることをテストしました。 このステップでは、systemdサービスとソケットファイルを作成することにより、アプリケーションサーバーを起動および停止するより堅牢な方法を実装します。
Gunicornソケットは起動時に作成され、接続をリッスンします。 接続が発生すると、systemdは接続を処理するためにGunicornプロセスを自動的に開始します。
sudo権限を持つGunicornのsystemdソケットファイルを作成して開くことから始めます。
sudo nano /etc/systemd/system/gunicorn.socket
内部では、ソケットを説明する[Unit]セクション、ソケットの場所を定義する[Socket]セクション、およびソケットがで作成されることを確認する[Install]セクションを作成します。適切な時点:
/etc/systemd/system/gunicorn.socket
[Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target
終了したら、ファイルを保存して閉じます。
次に、テキストエディタでsudo権限を持つGunicornのsystemdサービスファイルを作成して開きます。 サービスファイル名は、拡張子のソケットファイル名例外と一致する必要があります。
sudo nano /etc/systemd/system/gunicorn.service
[Unit]セクションから始めます。このセクションは、メタデータと依存関係を指定するために使用されます。 ここにサービスの説明を入力し、ネットワークターゲットに到達した後にのみこれを開始するようにinitシステムに指示します。 サービスはソケットファイルのソケットに依存しているため、その関係を示すためにRequiresディレクティブを含める必要があります。
/etc/systemd/system/gunicorn.service
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target
次に、[Service]セクションを開きます。 プロセスを実行するユーザーとグループを指定します。 プロセスはすべての関連ファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を付与します。 NginxがGunicornと簡単に通信できるように、www-dataグループにグループの所有権を付与します。
次に、作業ディレクトリをマップし、サービスの開始に使用するコマンドを指定します。 この場合、仮想環境内にインストールされているGunicorn実行可能ファイルへのフルパスを指定する必要があります。 プロセスを/runディレクトリ内に作成したUnixソケットにバインドして、プロセスがNginxと通信できるようにします。 journaldプロセスがGunicornログを収集できるように、すべてのデータを標準出力に記録します。 ここで、オプションのGunicornの微調整を指定することもできます。 3つのワーカープロセスを指定する例を次に示します。
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
--access-logfile - \
-k uvicorn.workers.UvicornWorker \
--workers 3 \
--bind unix:/run/gunicorn.sock \
myproject.asgi:application
最後に、[Install]セクションを追加します。 これにより、起動時にサービスを開始できるようにした場合に、このサービスを何にリンクするかがsystemdに通知されます。 通常のマルチユーザーシステムが稼働しているときに、このサービスを開始する必要があります。
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
--access-logfile - \
-k uvicorn.workers.UvicornWorker \
--workers 3 \
--bind unix:/run/gunicorn.sock \
myproject.asgi:application
[Install]
WantedBy=multi-user.target
これで、systemdサービスファイルが完成しました。 今すぐ保存して閉じます。
これで、Gunicornソケットを起動して有効にできます。 これにより、/run/gunicorn.sockで起動時にソケットファイルが作成されます。 そのソケットに接続が確立されると、systemdは自動的にgunicorn.serviceを起動してそれを処理します。
sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket
systemdサービスとソケットファイルを作成したので、ソケットファイルをチェックして操作が成功したことを確認します。
ステップ6—Gunicornソケットファイルを確認する
このステップでは、Gunicornソケットファイルを確認します。 まず、プロセスのステータスをチェックして、プロセスを開始できたかどうかを確認します。
sudo systemctl status gunicorn.socket
出力は次のようになります。
Output● gunicorn.socket - gunicorn socket
Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese>
Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago
Triggers: ● gunicorn.service
Listen: /run/gunicorn.sock (Stream)
Tasks: 0 (limit: 1137)
Memory: 0B
CGroup: /system.slice/gunicorn.socket
次に、/runディレクトリ内にgunicorn.sockファイルが存在するかどうかを確認します。
file /run/gunicorn.sock
Output/run/gunicorn.sock: socket
systemctl statusコマンドでエラーが発生した場合、またはディレクトリにgunicorn.sockファイルが見つからない場合は、Gunicornソケットが正しく作成されていないことを示しています。 次のように入力して、Gunicornソケットのログを確認します。
sudo journalctl -u gunicorn.socket
続行する前に、/etc/systemd/system/gunicorn.socketファイルをもう一度確認して、問題を修正してください。
ステップ7—ソケットアクティベーションのテスト
このステップでは、ソケットのアクティブ化をテストします。 現在、gunicorn.socketユニットのみを起動した場合、ソケットはまだ接続を受信していないため、gunicorn.serviceはまだアクティブになりません。 次のように入力して、これを確認できます。
sudo systemctl status gunicorn
Output● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)
ソケットアクティベーションメカニズムをテストするには、次のように入力して、curlを介してソケットに接続を送信できます。
curl --unix-socket /run/gunicorn.sock localhost
ターミナルでアプリケーションからHTML出力を受け取る必要があります。 これは、Gunicornが起動され、Djangoアプリケーションを提供できたことを示しています。 次のように入力して、Gunicornサービスが実行されていることを確認できます。
sudo systemctl status gunicorn
Output
● gunicorn.service - gunicorn daemon
Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
Active: active (running) since Thu 2021-06-10 21:03:29 UTC; 13s ago
TriggeredBy: ● gunicorn.socket
Main PID: 11682 (gunicorn)
Tasks: 4 (limit: 4682)
Memory: 98.5M
CGroup: /system.slice/gunicorn.service
├─11682 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 -k uvicorn.workers.UvicornWorker --bind unix:/run/gunicorn.sock myproject.asgi:application
├─11705 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 -k uvicorn.workers.UvicornWorker --bind unix:/run/gunicorn.sock myproject.asgi:application
├─11707 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 -k uvicorn.workers.UvicornWorker --bind unix:/run/gunicorn.sock myproject.asgi:application
└─11708 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 -k uvicorn.workers.UvicornWorker --bind unix:/run/gunicorn.sock myproject.asgi:application
Jun 10 21:03:29 django gunicorn[11705]: [2021-06-10 21:03:29 +0000] [11705] [INFO] ASGI 'lifespan' protocol appears unsupported.
Jun 10 21:03:29 django gunicorn[11705]: [2021-06-10 21:03:29 +0000] [11705] [INFO] Application startup complete.
Jun 10 21:03:30 django gunicorn[11707]: [2021-06-10 21:03:30 +0000] [11707] [INFO] Started server process [11707]
Jun 10 21:03:30 django gunicorn[11707]: [2021-06-10 21:03:30 +0000] [11707] [INFO] Waiting for application startup.
Jun 10 21:03:30 django gunicorn[11707]: [2021-06-10 21:03:30 +0000] [11707] [INFO] ASGI 'lifespan' protocol appears unsupported.
Jun 10 21:03:30 django gunicorn[11707]: [2021-06-10 21:03:30 +0000] [11707] [INFO] Application startup complete.
Jun 10 21:03:30 django gunicorn[11708]: [2021-06-10 21:03:30 +0000] [11708] [INFO] Started server process [11708]
Jun 10 21:03:30 django gunicorn[11708]: [2021-06-10 21:03:30 +0000] [11708] [INFO] Waiting for application startup.
Jun 10 21:03:30 django gunicorn[11708]: [2021-06-10 21:03:30 +0000] [11708] [INFO] ASGI 'lifespan' protocol appears unsupported.
Jun 10 21:03:30 django gunicorn[11708]: [2021-06-10 21:03:30 +0000] [11708] [INFO] Application startup complete.
curlからの出力またはsystemctl statusの出力が問題が発生したことを示している場合は、ログで詳細を確認してください。
sudo journalctl -u gunicorn
/etc/systemd/system/gunicorn.serviceファイルに問題がないか確認してください。 /etc/systemd/system/gunicorn.serviceファイルに変更を加えた場合は、デーモンをリロードしてサービス定義を再読み取りし、次のように入力してGunicornプロセスを再起動します。
sudo systemctl daemon-reload sudo systemctl restart gunicorn
続行する前に、必ず上記の問題のトラブルシューティングを行ってください。
ステップ8—GunicornへのプロキシパスにNginxを構成する
Gunicornがセットアップされたので、トラフィックをプロセスに渡すようにNginxを構成する必要があります。 このステップでは、Gunicornの前にNginxをセットアップして、その高性能な接続処理メカニズムと実装が容易なセキュリティ機能を利用します。
Nginxのsites-availableディレクトリに新しいサーバーブロックを作成して開くことから始めます。
sudo nano /etc/nginx/sites-available/myproject
内部で、新しいサーバーブロックを開きます。 まず、このブロックが通常のポート80でリッスンし、サーバーのドメイン名またはIPアドレスに応答するように指定します。
/ etc / nginx / sites-available / myproject
server {
listen 80;
server_name server_domain_or_IP;
}
次に、ファビコンの検索に関する問題を無視するようにNginxに指示します。 また、~/myprojectdir/staticディレクトリで収集した静的アセットの場所も通知します。 これらのファイルはすべて「/static」の標準URIプレフィックスを持っているため、これらのリクエストに一致するロケーションブロックを作成できます。
/ etc / nginx / sites-available / myproject
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/sammy/myprojectdir;
}
}
最後に、location / {}ブロックを作成して、他のすべてのリクエストに一致させます。 この場所に、Nginxインストールに含まれている標準のproxy_paramsファイルを含めてから、トラフィックをGunicornソケットに直接渡します。
/ etc / nginx / sites-available / myproject
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/sammy/myprojectdir;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
終了したら、ファイルを保存して閉じます。 これで、ファイルをsites-enabledディレクトリにリンクして有効にできます。
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
次のように入力して、構文エラーについてNginx構成をテストします。
sudo nginx -t
エラーが報告されていない場合は、次のように入力してNginxを再起動してください。
sudo systemctl restart nginx
最後に、ポート80の通常のトラフィックに対してファイアウォールを開く必要があります。 開発サーバーにアクセスする必要がなくなったため、ルールを削除してポート8000を開くこともできます。
sudo ufw delete allow 8000 sudo ufw allow 'Nginx Full'
これで、サーバーのドメインまたはIPアドレスに移動して、ロケットの画像が表示されたDjangoウェルカムページを表示できるようになります。
注: Nginxを構成したら、次のステップはSSL/TLSを使用してサーバーへのトラフィックを保護する必要があります。 これがないと、パスワードを含むすべての情報がプレーンテキストでネットワーク経由で送信されるため、これは重要です。
ドメイン名をお持ちの場合、トラフィックを保護するためにSSL証明書を取得する最も簡単な方法は、 Let'sEncryptを使用することです。 このガイドに従って、Ubuntu20.04でLet'sEncryptwithNginxを設定します。 このチュートリアルで作成したNginxサーバーブロックを使用して手順に従います。
ステップ9—NginxとGunicornのトラブルシューティング
この最後の手順でアプリケーションが表示されない場合は、インストールのトラブルシューティングを行う必要があります。
NginxはDjangoアプリケーションの代わりにデフォルトページを表示しています
Nginxがアプリケーションにプロキシする代わりにデフォルトのページを表示する場合は、通常、サーバーのIPアドレスまたはドメイン名を指すように/etc/nginx/sites-available/myprojectファイル内のserver_nameを調整する必要があることを意味します。
Nginxはserver_nameを使用して、リクエストへの応答に使用するサーバーブロックを決定します。 デフォルトのNginxページを受け取った場合、それはNginxがリクエストをサーバーブロックに明示的に一致させることができなかったことを示しているため、/etc/nginx/sites-available/defaultで定義されたデフォルトブロックにフォールバックしています。
プロジェクトのサーバーブロックのserver_nameよりも具体的である必要があります。
NginxはDjangoアプリケーションの代わりに502BadGatewayエラーを表示しています
502エラーは、Nginxがリクエストを正常にプロキシできないことを示します。 さまざまな構成の問題が502エラーで表されるため、適切にトラブルシューティングするには、より多くの情報が必要です。
詳細情報を探す主な場所は、Nginxのエラーログです。 一般に、これにより、プロキシイベント中に問題が発生した条件がわかります。 次のように入力して、Nginxエラーログを追跡します。
sudo tail -F /var/log/nginx/error.log
次に、ブラウザで別のリクエストを実行して、新しいエラーを生成します(ページを更新してみてください)。 ログに書き込まれた新しいエラーメッセージを受け取るはずです。 メッセージを見ると、問題を絞り込むのに役立つはずです。
次のメッセージが表示される場合があります。
connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)
これは、Nginxが指定された場所でgunicorn.sockファイルを見つけられなかったことを示しています。 /etc/nginx/sites-available/myprojectファイル内で定義されたproxy_passの場所を、gunicorn.socketsystemdユニットによって生成されたgunicorn.sockファイルの実際の場所と比較する必要があります。
/runディレクトリ内にgunicorn.sockファイルが見つからない場合は、通常、systemdソケットファイルでファイルを作成できなかったことを意味します。 Gunicornソケットファイルの確認に関するセクションに戻り、Gunicornのトラブルシューティング手順を実行します。
connect() to unix:/run/gunicorn.sock failed (13: Permission denied)
これは、権限の問題のためにNginxがGunicornソケットに接続できなかったことを示しています。 これは、プロシージャがsudoユーザーの代わりにrootユーザーを使用する場合に発生する可能性があります。 systemdはGunicornソケットファイルを作成できますが、Nginxはそれにアクセスできません。
これは、ルートディレクトリ(/)とgunicorn.sockファイルの間のいずれかの時点でアクセス許可が制限されている場合に発生する可能性があります。 nameiコマンドにソケットファイルへの絶対パスを渡すことにより、ソケットファイルとその各親ディレクトリのアクセス許可と所有権の値を確認できます。
namei -l /run/gunicorn.sock
Outputf: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock
出力には、各ディレクトリコンポーネントの権限が表示されます。 アクセス許可(最初の列)、所有者(2番目の列)、およびグループ所有者(3番目の列)を確認することで、ソケットファイルに許可されているアクセスの種類を把握できます。
上記の例では、ソケットファイルとソケットファイルにつながる各ディレクトリに、ワールド読み取りおよび実行権限があります(ディレクトリの権限列は、---ではなくr-xで終わります)。 Nginxプロセスはソケットに正常にアクセスできるはずです。
ソケットにつながるディレクトリのいずれかにワールド読み取りおよび実行権限がない場合、Nginxは、ワールド読み取りおよび実行権限を許可するか、Nginxが含まれるグループにグループ所有権が付与されていることを確認しない限り、ソケットにアクセスできません。の。
Djangoが表示されています:「サーバーに接続できませんでした:接続が拒否されました」
Webブラウザでアプリケーションの一部にアクセスしようとしたときにDjangoから受け取る可能性のあるメッセージの1つは次のとおりです。
OperationalError at /admin/login/
could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432?
これは、DjangoがPostgresデータベースに接続できないことを示しています。 次のように入力して、Postgresインスタンスが実行されていることを確認します。
sudo systemctl status postgresql
そうでない場合は、次のように入力して、起動し、起動時に自動的に起動できるようにすることができます(まだ設定されていない場合)。
sudo systemctl start postgresql sudo systemctl enable postgresql
それでも問題が解決しない場合は、~/myprojectdir/myproject/settings.pyファイルで定義されているデータベース設定が正しいことを確認してください。
さらなるトラブルシューティング
追加のトラブルシューティングについては、ログが根本原因の絞り込みに役立ちます。 それぞれを順番にチェックし、問題のある領域を示すメッセージを探します。
次のログが役立つ場合があります。
sudo journalctl -u nginxと入力して、Nginxプロセスログを確認します。sudo less /var/log/nginx/access.logと入力して、Nginxアクセスログを確認します。sudo less /var/log/nginx/error.logと入力して、Nginxエラーログを確認します。sudo journalctl -u gunicornと入力して、Gunicornのアプリケーションログを確認します。sudo journalctl -u gunicorn.socketと入力して、Gunicornソケットログを確認します。
構成またはアプリケーションを更新するときに、変更に適応するためにプロセスを再起動する必要がある場合があります。
Djangoアプリケーションを更新する場合は、Gunicornプロセスを再起動して、次のように入力することで変更を取得できます。
sudo systemctl restart gunicorn
Gunicornのソケットまたはサービスファイルを変更した場合は、デーモンをリロードし、次のように入力してプロセスを再開します。
sudo systemctl daemon-reload sudo systemctl restart gunicorn.socket gunicorn.service
Nginxサーバーブロックの構成を変更する場合は、次のように入力して構成をテストしてからNginxをテストします。
sudo nginx -t && sudo systemctl restart nginx
これらのコマンドは、構成を調整するときに変更を取得するのに役立ちます。
結論
このガイドでは、独自の仮想環境でASGIDjangoプロジェクトをセットアップしました。 クライアントリクエストを非同期に変換してDjangoが処理できるように、GunicornとUvicornを設定しました。 その後、クライアント接続を処理し、クライアントの要求に応じて正しいプロジェクトを提供するリバースプロキシとして機能するようにNginxを設定します。
Djangoは、多くの一般的な要素を提供することでプロジェクトとアプリケーションの作成プロセスを合理化し、独自の要素に集中できるようにします。 この記事で説明する一般的なツールチェーンを活用することで、単一のサーバーから作成したアプリケーションを提供できます。